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:11:04 UTC

[17/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

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 all info from MANIFEST
- Adding the concept of a Bundle and refactoring NarClassLoaders to pass Bundles to ExtensionManager
- Adding logic to fail start-up when multiple NARs with same coordinates exist, moving Bundle classes to framework API
- Refactoring bundle API to classes and creating BundleCoordinate
- Updating FlowController to use BundleCoordinate

- Updating the UI and DTO model to support showing bundle details that loaded an extension type.
- Adding bundle details for processor canvas node, processor dialogs, controller service dialogs, and reporting task dialogs.
- Updating the formating of the bundle coordinates.
- Addressing text overflow in the configuration/details dialog.
- Fixing self referencing functions.
- Updating extension UI mapping to incorporate bundle coordinates.
- Discovering custom UIs through the supplied bundles.
- Adding verification methods for creating extensions through the rest api.
- Only returning extensions that are common amongst all nodes.
- Rendering the ghost processors using a dotted border.
- Adding bundle details to the flow.xml.
- Loading NiFi build and version details from the framework NAR.
- Removing properties for build and version details.
- Wiring together front end and back end changes.
- Including bundle coordinates in the component data model.
- Wiring together component data model and flow.xml.
- Addressing issue when resolve unvesioned dependent NARs.

Updating unit tests to pass based on framework changes
- Fixing logging of extension types during start up

- Allowing the application to start if there is a compatible bundle found. - Reporting missing bundle when the a compatible bundle is not found. - Fixing table height in new component dialogs.

Fixing chechstyle error and increasing test timeout for TestStandardControllerServiceProvider
- Adding ability to change processor type at runtime
- Adding backend code to change type for controller services

- Cleaning up instance classloaders for temp components.
- Creating a dialog for changing the version of a component.
- Updating the formatting of the component type and bundle throughout.
- Updating the new component dialogs to support selecting source group.
- Cleaning up new component dialogs.
- Cleaning up documentation in the cluster node endpoint.

Adding missing include in nifi-web-ui pom compressor plugin
- Refactoring so ConfigurableComponent provides getLogger() and so the nodes provide the ConfigurableComponent
- Creating LoggableComponent to pass around the component, logger, and coordinate with in the framework

- Finishing clean up following rebase.

Calling lifecycle methods for add and remove when changing versions of a component
- Introducing verifyCanUpdateBundle(coordinate) to ConfiguredComponent, and adding unit tests

- Ensuring documentation is available for all components. Including those of the same type that are loaded from different bundles.

Adding lookup from ClassLoader to Bundle, adding fix for instance class loading to include all parent NARs, and adding additional unit tests for FlowController
- Adding validation to ensure referenced controller services implement the required API
- Fixing template instantiation to look up compatible bundle

- Requiring services/reporting tasks to be disabled/stopped.
- Only supporting a change version option when the item has multiple versions available.
- Limiting the possible new controller services to the applicable API version.
- Showing the implemented API versions for Controller Services.
- Updating the property descriptor tooltip to indicate the required service requirements.
- Introducing version based sorting in the new component dialog, change version dialog, and new controller service dialog.
- Addressing remainder of the issues from recent rebase.

Ensuring bundles have been added to the flow before proposing a flow, and incorporating bundle information into flow fingerprinting
- Refactoring the way missing bundles work to retain the desired bundle if available
- Fixing logger.isDebugEnabled to be logger.isTraceEnabled

- Auditing when user changes the bundle. - Ensuring bundle details are present in templates.

Moving standard prioritizers to framework NAR and refactoring ExtensionManager logic to handle cases where an extension is in a JAR directly in the lib directory

- Ensuring all nodes attempt to instantiate the same template instance when the available bundles may differ. - Fixing the auditing of copy/paste and template instantiation. - Running addtional verification methods when running standalone.

Refactoring controller service invocation handler to allow updating the node used by the invocation handler
- Ensuring the bundles in a proposed flow are compatible with the current instance when the current instance has no flow is going to accept the proposed flow
- Merging whether multiple versions of the component are available
- Setting NAR plugin back to current released version
- Cleaning up DocGenerator to not process multiple times

Addressing incorrect usage of nf.Common. - Using formatType in the new component type dialogs.

Improving error messages when looking for bundles

Addressing comments from PR. - Fixing references to global nf namespace. - Fixing injection of nfProcessGroupConfiguration in nfComponentVersion. - Fixing web api integration tests.

Not rendering unversioned in help documentation. - Ensuring the isExtentionMissing flag is correct after changing the component type.

Adding synchronization in node classes to ensure changing component can't occur when component is running, introducing MissingBundleException for better reporting when a node can't join cluster due to a missing bundle, and bumping NAR plugin to released version 1.2.0

Adding concept of missing components to fingerprinting to ensure nodes agree on missing components when joining a cluster

NIFI-3380: NIFI-3520: - Fixing hive nar dependency. - Marking DBCPService as provided. - Skipping services that require instance classloading and are cobundled with their service API. - Skipping components that require instance classloading and reference service APIs that are cobundled. - Addressing UI issues in the new component dialogs when re-opening with a filter applied.

Fixing checkstyles issue and adding back assume checks to distributed cache server test

Ensuring new component types are sorted correctly when shown initially.

This closes #1585.


Project: http://git-wip-us.apache.org/repos/asf/nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/d90cf846
Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/d90cf846
Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/d90cf846

Branch: refs/heads/master
Commit: d90cf846b9dcd49acdeac7bb5fcd13ee80dcdba6
Parents: 2dd6112
Author: Bryan Bende <bb...@apache.org>
Authored: Mon Jan 23 10:33:12 2017 -0500
Committer: Mark Payne <ma...@hotmail.com>
Committed: Fri Mar 24 11:06:44 2017 -0400

----------------------------------------------------------------------
 .../nifi/components/ConfigurableComponent.java  |   1 +
 nifi-assembly/pom.xml                           |   5 +
 .../AbstractNotificationService.java            |   1 +
 .../org/apache/nifi/util/NiFiProperties.java    |  37 --
 .../NiFiProperties/conf/nifi.blank.properties   |   1 -
 .../NiFiProperties/conf/nifi.missing.properties |   1 -
 .../NiFiProperties/conf/nifi.properties         |   1 -
 .../src/main/asciidoc/administration-guide.adoc |   1 -
 .../src/main/asciidoc/developer-guide.adoc      |  10 +
 .../java/org/apache/nifi/bundle/Bundle.java     |  48 ++
 .../apache/nifi/bundle/BundleCoordinate.java    |  90 ++++
 .../org/apache/nifi/bundle/BundleDetails.java   | 188 +++++++
 .../StateProviderInitializationContext.java     |   7 +
 .../nifi/bundle/BundleCoordinateTest.java       |  74 +++
 .../apache/nifi/bundle/BundleDetailsTest.java   | 151 ++++++
 ....apache.nifi.provenance.ProvenanceRepository |  15 +
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../nifi-framework-nar/pom.xml                  |   4 +
 .../authorization/AuthorizerFactoryBean.java    |  14 +-
 .../org/apache/nifi/web/api/dto/BundleDTO.java  | 109 +++++
 .../web/api/dto/ControllerServiceApiDTO.java    |  81 ++++
 .../nifi/web/api/dto/ControllerServiceDTO.java  |  65 +++
 .../nifi/web/api/dto/DocumentedTypeDTO.java     |  54 +++
 .../apache/nifi/web/api/dto/ProcessorDTO.java   |  47 ++
 .../nifi/web/api/dto/PropertyDescriptorDTO.java |  20 +-
 .../nifi/web/api/dto/ReportingTaskDTO.java      |  47 ++
 .../apache/nifi/web/api/dto/TemplateDTO.java    |   2 +-
 .../InstantiateTemplateRequestEntity.java       |  39 +-
 .../ConfigurableComponentInitializer.java       |  45 --
 .../apache/nifi/documentation/DocGenerator.java |  99 ++--
 .../html/HtmlDocumentationWriter.java           |   2 +-
 .../init/ControllerServiceInitializer.java      |  61 ---
 .../init/ProcessorInitializer.java              |  60 ---
 .../init/ReportingTaskingInitializer.java       |  59 ---
 .../documentation/mock/MockComponentLogger.java | 258 ----------
 .../mock/MockConfigurationContext.java          |  48 --
 ...kControllerServiceInitializationContext.java |  67 ---
 .../mock/MockControllerServiceLookup.java       |  63 ---
 .../mock/MockNodeTypeProvider.java              |  40 --
 .../documentation/mock/MockProcessContext.java  | 116 -----
 .../MockProcessorInitializationContext.java     |  67 ---
 .../MockReportingInitializationContext.java     |  83 ----
 .../documentation/util/ReflectionUtils.java     | 133 -----
 .../nifi/documentation/DocGeneratorTest.java    |  31 +-
 .../html/HtmlDocumentationWriterTest.java       |   8 +-
 .../html/ProcessorDocumentationWriterTest.java  |   2 +-
 .../src/test/resources/conf/nifi.properties     |   1 -
 .../coordination/node/DisconnectionCode.java    |   5 +
 .../nifi/cluster/protocol/StandardDataFlow.java |  16 +-
 .../protocol/jaxb/message/AdaptedDataFlow.java  |  11 +
 .../protocol/jaxb/message/DataFlowAdapter.java  |   3 +-
 .../jaxb/message/TestJaxbProtocolUtils.java     |   3 +-
 .../http/StandardHttpResponseMapper.java        |   8 +
 .../ControllerServiceTypesEndpointMerger.java   |  51 ++
 .../PrioritizerTypesEndpointMerger.java         |  51 ++
 .../endpoints/ProcessorTypesEndpointMerger.java |  51 ++
 .../ReportingTaskTypesEndpointMerger.java       |  51 ++
 .../node/NodeClusterCoordinator.java            |   4 +-
 .../cluster/manager/DocumentedTypesMerger.java  |  40 ++
 .../cluster/manager/ProcessorEntityMerger.java  |   9 +
 .../flow/TestPopularVoteFlowElection.java       |   3 +-
 .../node/TestNodeClusterCoordinator.java        |  15 +-
 .../cluster/integration/NopStateProvider.java   |   1 +
 .../src/test/resources/conf/nifi.properties     |   1 -
 .../apache/nifi/cluster/protocol/DataFlow.java  |   7 +
 .../controller/AbstractConfiguredComponent.java | 184 +++++--
 .../nifi/controller/ConfiguredComponent.java    |  15 +
 .../nifi/controller/LoggableComponent.java      |  54 +++
 .../apache/nifi/controller/ProcessorNode.java   |  23 +-
 .../nifi/controller/ReportingTaskNode.java      |   2 +
 .../ProcessorInstantiationException.java        |   3 +
 .../reporting/ReportingTaskProvider.java        |  16 +-
 .../ControllerServiceInvocationHandler.java     |  30 ++
 .../service/ControllerServiceNode.java          |  18 +
 .../service/ControllerServiceProvider.java      |   4 +-
 .../org/apache/nifi/services/FlowService.java   |  10 +-
 .../apache/nifi/controller/FlowController.java  | 426 +++++++++++-----
 .../nifi/controller/MissingBundleException.java |  47 ++
 .../nifi/controller/ProcessorDetails.java       | 111 +++++
 .../nifi/controller/StandardFlowService.java    | 192 +++++---
 .../controller/StandardFlowSynchronizer.java    | 200 ++++++--
 .../nifi/controller/StandardProcessorNode.java  | 190 ++++----
 .../apache/nifi/controller/TemplateUtils.java   |  35 +-
 .../reporting/AbstractReportingTaskNode.java    |  67 ++-
 .../reporting/ReportingTaskDetails.java         |  50 ++
 .../reporting/StandardReportingTaskNode.java    |  17 +-
 .../serialization/FlowFromDOMFactory.java       |  36 +-
 .../serialization/FlowSynchronizer.java         |   4 +-
 .../serialization/StandardFlowSerializer.java   |  66 ++-
 .../service/ControllerServiceDetails.java       |  64 +++
 .../service/ControllerServiceLoader.java        |  52 +-
 ...ndardControllerServiceInvocationHandler.java |  97 ++++
 .../service/StandardControllerServiceNode.java  |  89 +++-
 .../StandardControllerServiceProvider.java      | 151 ++----
 ...ndardStateProviderInitializationContext.java |  10 +-
 .../manager/StandardStateManagerProvider.java   |  25 +-
 .../nifi/fingerprint/FingerprintFactory.java    |  48 +-
 .../nifi/persistence/FlowConfigurationDAO.java  |   4 +-
 .../StandardXMLFlowConfigurationDAO.java        |   3 +-
 .../apache/nifi/processor/GhostProcessor.java   |   2 +
 .../nifi/reporting/GhostReportingTask.java      |   3 +
 .../java/org/apache/nifi/util/BundleUtils.java  | 143 ++++++
 .../src/main/resources/FlowConfiguration.xsd    |  11 +
 .../StandardFlowSynchronizerSpec.groovy         |  28 +-
 .../controller/StandardFlowServiceTest.java     |  22 +-
 .../nifi/controller/TestFlowController.java     | 486 +++++++++++++++++--
 .../controller/TestStandardProcessorNode.java   |  91 ++--
 .../scheduling/TestProcessorLifecycle.java      | 195 +++++---
 .../TestStandardProcessScheduler.java           |  70 +--
 .../StandardControllerServiceProviderTest.java  |  12 +-
 .../TestStandardControllerServiceProvider.java  | 162 ++++---
 .../local/TestWriteAheadLocalStateProvider.java |   6 +
 .../zookeeper/TestZooKeeperStateProvider.java   |   6 +
 .../fingerprint/FingerprintFactoryTest.java     |  33 ++
 ...org.apache.nifi.controller.ControllerService |   4 +
 .../org.apache.nifi.processor.Processor         |   3 +-
 .../org.apache.nifi.reporting.ReportingTask     |  15 +
 .../src/test/resources/conf/nifi.properties     |   1 -
 .../conf/scale-positions-flow-0.7.0.xml         |  44 +-
 .../src/test/resources/logback-test.xml         |   1 +
 .../test/resources/nifi-with-remote.properties  |   1 -
 .../src/test/resources/nifi.properties          |   1 -
 .../nifi/fingerprint/flow3-with-bundle-1.xml    |  53 ++
 .../nifi/fingerprint/flow3-with-bundle-2.xml    |  53 ++
 .../fingerprint/flow3-with-missing-bundle.xml   |  53 ++
 .../nifi/fingerprint/flow3-with-no-bundle.xml   |  48 ++
 .../fingerprint/flow4-with-different-bundle.xml |  53 ++
 .../test/resources/nifi/fingerprint/flow4.xml   |  53 ++
 .../nifi/fingerprint/validating-flow.xml        |  10 +
 .../nifi-framework/nifi-nar-utils/pom.xml       |  15 +
 .../init/ConfigurableComponentInitializer.java  |  45 ++
 ...ConfigurableComponentInitializerFactory.java |  44 ++
 .../nifi/init/ControllerServiceInitializer.java |  59 +++
 .../apache/nifi/init/ProcessorInitializer.java  |  58 +++
 .../org/apache/nifi/init/ReflectionUtils.java   | 133 +++++
 .../nifi/init/ReportingTaskingInitializer.java  |  57 +++
 .../apache/nifi/mock/MockComponentLogger.java   | 258 ++++++++++
 .../nifi/mock/MockConfigurationContext.java     |  48 ++
 ...kControllerServiceInitializationContext.java |  68 +++
 .../nifi/mock/MockControllerServiceLookup.java  |  63 +++
 .../apache/nifi/mock/MockNodeTypeProvider.java  |  40 ++
 .../apache/nifi/mock/MockProcessContext.java    | 116 +++++
 .../MockProcessorInitializationContext.java     |  68 +++
 .../MockReportingInitializationContext.java     |  83 ++++
 .../org/apache/nifi/nar/ExtensionManager.java   | 356 +++++++++++---
 .../org/apache/nifi/nar/ExtensionMapping.java   | 106 ++--
 .../java/org/apache/nifi/nar/NarBundleUtil.java |  74 +++
 .../org/apache/nifi/nar/NarClassLoader.java     |  10 +-
 .../org/apache/nifi/nar/NarClassLoaders.java    | 216 +++++----
 .../java/org/apache/nifi/nar/NarCloseable.java  |  18 +-
 .../org/apache/nifi/nar/NarManifestEntry.java   |  48 ++
 .../nifi/nar/NarThreadContextClassLoader.java   |  23 +-
 .../java/org/apache/nifi/nar/NarUnpacker.java   | 164 ++++---
 .../org/apache/nifi/nar/NarBundleUtilTest.java  | 101 ++++
 .../nar/NarThreadContextClassLoaderTest.java    |  47 +-
 .../org/apache/nifi/nar/NarUnpackerTest.java    |  29 +-
 .../org.apache.nifi.processor.Processor         |  16 +
 .../resources/NarUnpacker/conf/nifi.properties  |   1 -
 .../nar-with-versioning/META-INF/MANIFEST.MF    |  15 +
 .../nar-without-dependency/META-INF/MANIFEST.MF |  12 +
 .../nar-without-versioning/META-INF/MANIFEST.MF |   7 +
 .../src/test/resources/nifi.properties          |   1 -
 .../ProtectedNiFiPropertiesGroovyTest.groovy    |   2 +-
 ...ensitive_properties_protected_aes.properties |   1 -
 .../test/resources/conf/nifi.blank.properties   |   1 -
 .../test/resources/conf/nifi.missing.properties |   1 -
 .../src/test/resources/conf/nifi.properties     |   1 -
 ...fi_with_additional_sensitive_keys.properties |   3 +-
 ...ensitive_properties_protected_aes.properties |   1 -
 ...cursive_additional_sensitive_keys.properties |   1 -
 ...ensitive_properties_protected_aes.properties |   1 -
 ...tive_properties_protected_aes_128.properties |   3 +-
 ...erties_protected_aes_128_password.properties |   1 -
 ..._protected_aes_multiple_malformed.properties |   3 +-
 ...es_protected_aes_single_malformed.properties |   1 -
 ...tive_properties_protected_unknown.properties |   1 -
 ..._sensitive_properties_unprotected.properties |   1 -
 ...properties_unprotected_extra_line.properties |   1 -
 .../nifi-framework/nifi-resources/pom.xml       |   8 -
 .../src/main/resources/conf/nifi.properties     |   9 +-
 .../nifi-framework/nifi-runtime/pom.xml         |   5 +
 .../src/main/java/org/apache/nifi/NiFi.java     |  39 +-
 .../NiFiProperties/conf/nifi.properties         |   1 -
 ...ensitive_properties_protected_aes.properties |   1 -
 ...rties_protected_aes_different_key.properties |   1 -
 .../src/test/resources/nifi.properties          |   1 -
 .../nifi-standard-prioritizers/pom.xml          |  40 ++
 .../prioritizer/FirstInFirstOutPrioritizer.java |  42 ++
 .../NewestFlowFileFirstPrioritizer.java         |  42 ++
 .../OldestFlowFileFirstPrioritizer.java         |  42 ++
 .../PriorityAttributePrioritizer.java           |  86 ++++
 ...org.apache.nifi.flowfile.FlowFilePrioritizer |  18 +
 .../prioritizer/NewestFirstPrioritizerTest.java |  66 +++
 .../prioritizer/OldestFirstPrioritizerTest.java |  66 +++
 .../PriorityAttributePrioritizerTest.java       | 117 +++++
 .../org/apache/nifi/web/server/JettyServer.java | 142 ++----
 .../nifi-web/nifi-ui-extension/pom.xml          |   4 -
 .../nifi/ui/extension/UiExtensionMapping.java   |  28 +-
 .../nifi/audit/ControllerServiceAuditor.java    |   6 +
 .../java/org/apache/nifi/audit/NiFiAuditor.java |  25 +-
 .../org/apache/nifi/audit/ProcessorAuditor.java |   6 +
 .../apache/nifi/audit/ReportingTaskAuditor.java |   6 +
 .../org/apache/nifi/audit/SnippetAuditor.java   |   5 +-
 .../nifi/authorization/AuthorizableLookup.java  |  24 +-
 .../ConfigurableComponentAuthorizable.java      |   5 +
 .../StandardAuthorizableLookup.java             |  70 ++-
 .../authorization/TemplateAuthorizable.java     |  48 --
 .../TemplateContentsAuthorizable.java           |  39 ++
 .../org/apache/nifi/web/NiFiServiceFacade.java  |  56 ++-
 .../nifi/web/StandardNiFiServiceFacade.java     |  44 +-
 .../nifi/web/api/ApplicationResource.java       |   5 +
 .../apache/nifi/web/api/ControllerResource.java |  50 +-
 .../nifi/web/api/ControllerServiceResource.java |   7 +-
 .../org/apache/nifi/web/api/FlowResource.java   | 121 ++++-
 .../nifi/web/api/ProcessGroupResource.java      | 139 ++++--
 .../apache/nifi/web/api/ProcessorResource.java  |   7 +-
 .../nifi/web/api/ReportingTaskResource.java     |   7 +-
 .../apache/nifi/web/api/TemplateResource.java   |   4 +-
 .../org/apache/nifi/web/api/dto/DtoFactory.java | 237 +++++++--
 .../nifi/web/controller/ControllerFacade.java   |  77 ++-
 .../nifi/web/dao/ControllerServiceDAO.java      |  11 +-
 .../org/apache/nifi/web/dao/ProcessorDAO.java   |   7 +
 .../apache/nifi/web/dao/ReportingTaskDAO.java   |  12 +-
 .../org/apache/nifi/web/dao/TemplateDAO.java    |   5 +-
 .../apache/nifi/web/dao/impl/ComponentDAO.java  |  23 +
 .../dao/impl/StandardControllerServiceDAO.java  |  38 +-
 .../nifi/web/dao/impl/StandardProcessorDAO.java |  38 +-
 .../web/dao/impl/StandardReportingTaskDAO.java  |  55 ++-
 .../nifi/web/dao/impl/StandardTemplateDAO.java  |  22 +-
 .../web/dao/impl/StandardTemplateDAOSpec.groovy |  57 +--
 .../accesscontrol/AccessControlHelper.java      |   4 +-
 .../accesscontrol/ITAccessTokenEndpoint.java    |   4 +-
 .../access-control/nifi-flow.properties         |   1 -
 .../resources/access-control/nifi.properties    |   1 -
 .../test/resources/site-to-site/nifi.properties |   1 -
 .../nifi-web/nifi-web-docs/pom.xml              |   5 +
 .../nifi/web/docs/DocumentationController.java  |  11 +-
 .../main/webapp/WEB-INF/jsp/documentation.jsp   |  87 +++-
 .../src/main/webapp/js/application.js           |  90 +++-
 .../LoginIdentityProviderFactoryBean.java       |  14 +-
 .../nifi-framework/nifi-web/nifi-web-ui/pom.xml |   1 +
 .../main/resources/filters/canvas.properties    |   1 +
 .../src/main/webapp/WEB-INF/pages/canvas.jsp    |   1 +
 .../canvas/component-version-dialog.jsp         |  63 +++
 .../canvas/controller-service-configuration.jsp |   8 +
 .../canvas/new-controller-service-dialog.jsp    |  15 +-
 .../partials/canvas/new-processor-dialog.jsp    |  15 +-
 .../canvas/new-reporting-task-dialog.jsp        |  16 +-
 .../partials/canvas/processor-configuration.jsp |   4 +
 .../canvas/reporting-task-configuration.jsp     |   4 +
 .../partials/history/action-details-dialog.jsp  |   2 +-
 .../WEB-INF/partials/processor-details.jsp      |   9 +-
 .../src/main/webapp/css/controller-service.css  |  23 +-
 .../nifi-web-ui/src/main/webapp/css/dialog.css  |   9 +
 .../nifi-web-ui/src/main/webapp/css/graph.css   |  16 +-
 .../css/new-controller-service-dialog.css       |  43 +-
 .../main/webapp/css/new-processor-dialog.css    |  46 +-
 .../webapp/css/new-reporting-task-dialog.css    |  49 +-
 .../main/webapp/css/processor-configuration.css |   6 +
 .../src/main/webapp/css/processor-details.css   |   6 +
 .../src/main/webapp/css/reporting-task.css      |   6 +
 .../webapp/js/jquery/combo/jquery.combo.css     |   4 -
 .../propertytable/jquery.propertytable.js       | 122 +++--
 .../js/jquery/tagcloud/jquery.tagcloud.css      |  44 +-
 .../js/jquery/tagcloud/jquery.tagcloud.js       |  50 +-
 .../components/nf-ng-processor-component.js     | 117 +++--
 .../src/main/webapp/js/nf/canvas/nf-actions.js  |  31 +-
 .../webapp/js/nf/canvas/nf-canvas-bootstrap.js  |  10 +-
 .../webapp/js/nf/canvas/nf-component-version.js | 341 +++++++++++++
 .../main/webapp/js/nf/canvas/nf-context-menu.js |  27 +-
 .../js/nf/canvas/nf-controller-service.js       |  28 +-
 .../js/nf/canvas/nf-controller-services.js      | 203 ++++++--
 .../js/nf/canvas/nf-processor-configuration.js  |   3 +-
 .../main/webapp/js/nf/canvas/nf-processor.js    |  54 ++-
 .../webapp/js/nf/canvas/nf-reporting-task.js    |   5 +-
 .../src/main/webapp/js/nf/canvas/nf-settings.js | 195 ++++++--
 .../src/main/webapp/js/nf/nf-common.js          | 251 +++++++++-
 .../main/webapp/js/nf/nf-processor-details.js   |   3 +-
 .../nifi-framework/pom.xml                      |   1 +
 nifi-nar-bundles/nifi-framework-bundle/pom.xml  |   5 +
 .../additionalDetails.html                      |   2 +-
 .../nifi-hive-bundle/nifi-hive-nar/pom.xml      |   5 +
 .../nifi-hive-processors/pom.xml                |   6 +
 .../apache/nifi/dbcp/hive/HiveDBCPService.java  |  32 --
 .../nifi-hive-services-api-nar/pom.xml          |  46 ++
 .../nifi-hive-services-api/pom.xml              |  39 ++
 .../apache/nifi/dbcp/hive/HiveDBCPService.java  |  32 ++
 nifi-nar-bundles/nifi-hive-bundle/pom.xml       |   2 +
 .../additionalDetails.html                      |   2 +-
 .../nifi-jms-bundle/nifi-jms-processors/pom.xml |   1 +
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../nifi-jolt-transform-json-ui/pom.xml         |  16 +
 .../META-INF/nifi-processor-configuration       |   2 +-
 .../nifi-standard-nar/pom.xml                   |   4 -
 .../nifi-standard-prioritizers/pom.xml          |  40 --
 .../prioritizer/FirstInFirstOutPrioritizer.java |  42 --
 .../NewestFlowFileFirstPrioritizer.java         |  42 --
 .../OldestFlowFileFirstPrioritizer.java         |  42 --
 .../PriorityAttributePrioritizer.java           |  86 ----
 ...org.apache.nifi.flowfile.FlowFilePrioritizer |  18 -
 .../prioritizer/NewestFirstPrioritizerTest.java |  66 ---
 .../prioritizer/OldestFirstPrioritizerTest.java |  66 ---
 .../PriorityAttributePrioritizerTest.java       | 117 -----
 .../nifi-standard-processors/pom.xml            |   1 +
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   4 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../additionalDetails.html                      |   2 +-
 .../nifi/controller/MonitorMemoryTest.java      |  24 +-
 .../src/test/resources/nifi.properties          |   1 -
 nifi-nar-bundles/nifi-standard-bundle/pom.xml   |   6 -
 .../nifi-dbcp-service/pom.xml                   |   1 +
 .../cache/server/TestServerAndClient.java       |  56 +++
 .../additionalDetails.html                      |   2 +-
 .../nifi-update-attribute-ui/pom.xml            |  20 +
 .../META-INF/nifi-processor-configuration       |   2 +-
 .../additionalDetails.html                      |   2 +-
 nifi-nar-bundles/pom.xml                        |  30 +-
 .../src/test/resources/nifi_default.properties  |   1 -
 ...ensitive_properties_protected_aes.properties |   3 -
 ...erties_protected_aes_password_128.properties |   3 -
 ..._sensitive_properties_unprotected.properties |   3 -
 ...ensitive_properties_protected_aes.properties |   1 -
 ...properties_protected_aes_password.properties |   1 -
 ...erties_protected_aes_password_128.properties |   1 -
 ..._sensitive_properties_unprotected.properties |   1 -
 ...cted_and_empty_protection_schemes.properties |   1 -
 .../test/resources/localhost/nifi.properties    |   1 -
 pom.xml                                         |  13 +-
 359 files changed, 10238 insertions(+), 3901 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-api/src/main/java/org/apache/nifi/components/ConfigurableComponent.java
----------------------------------------------------------------------
diff --git a/nifi-api/src/main/java/org/apache/nifi/components/ConfigurableComponent.java b/nifi-api/src/main/java/org/apache/nifi/components/ConfigurableComponent.java
index 2e9cb4d..cd8c781 100644
--- a/nifi-api/src/main/java/org/apache/nifi/components/ConfigurableComponent.java
+++ b/nifi-api/src/main/java/org/apache/nifi/components/ConfigurableComponent.java
@@ -80,4 +80,5 @@ public interface ConfigurableComponent {
      * component
      */
     String getIdentifier();
+
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-assembly/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-assembly/pom.xml b/nifi-assembly/pom.xml
index f17c3c6..0a810f6 100755
--- a/nifi-assembly/pom.xml
+++ b/nifi-assembly/pom.xml
@@ -385,6 +385,11 @@ language governing permissions and limitations under the License. -->
         </dependency>
         <dependency>
             <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-hive-services-api-nar</artifactId>
+            <type>nar</type>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
             <artifactId>nifi-hive-nar</artifactId>
             <type>nar</type>
         </dependency>

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/AbstractNotificationService.java
----------------------------------------------------------------------
diff --git a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/AbstractNotificationService.java b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/AbstractNotificationService.java
index 109b1bc..bd475fa 100644
--- a/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/AbstractNotificationService.java
+++ b/nifi-bootstrap/src/main/java/org/apache/nifi/bootstrap/notification/AbstractNotificationService.java
@@ -34,4 +34,5 @@ public abstract class AbstractNotificationService extends AbstractConfigurableCo
     public String getIdentifier() {
         return identifier;
     }
+
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java
----------------------------------------------------------------------
diff --git a/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java b/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java
index 2855dab..3d657fb 100644
--- a/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java
+++ b/nifi-commons/nifi-properties/src/main/java/org/apache/nifi/util/NiFiProperties.java
@@ -24,12 +24,9 @@ import java.net.InetSocketAddress;
 import java.nio.file.InvalidPathException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -58,7 +55,6 @@ public abstract class NiFiProperties {
     public static final String LOGIN_IDENTITY_PROVIDER_CONFIGURATION_FILE = "nifi.login.identity.provider.configuration.file";
     public static final String REPOSITORY_DATABASE_DIRECTORY = "nifi.database.directory";
     public static final String RESTORE_DIRECTORY = "nifi.restore.directory";
-    public static final String VERSION = "nifi.version";
     public static final String WRITE_DELAY_INTERVAL = "nifi.flowservice.writedelay.interval";
     public static final String AUTO_RESUME_STATE = "nifi.flowcontroller.autoResumeState";
     public static final String FLOW_CONTROLLER_GRACEFUL_SHUTDOWN_PERIOD = "nifi.flowcontroller.graceful.shutdown.period";
@@ -141,8 +137,6 @@ public abstract class NiFiProperties {
     public static final String SECURITY_NEED_CLIENT_AUTH = "nifi.security.needClientAuth";
     public static final String SECURITY_USER_AUTHORIZER = "nifi.security.user.authorizer";
     public static final String SECURITY_USER_LOGIN_IDENTITY_PROVIDER = "nifi.security.user.login.identity.provider";
-    public static final String SECURITY_CLUSTER_AUTHORITY_PROVIDER_PORT = "nifi.security.cluster.authority.provider.port";
-    public static final String SECURITY_CLUSTER_AUTHORITY_PROVIDER_THREADS = "nifi.security.cluster.authority.provider.threads";
     public static final String SECURITY_OCSP_RESPONDER_URL = "nifi.security.ocsp.responder.url";
     public static final String SECURITY_OCSP_RESPONDER_CERTIFICATE = "nifi.security.ocsp.responder.certificate";
     public static final String SECURITY_IDENTITY_MAPPING_PATTERN_PREFIX = "nifi.security.identity.mapping.pattern.";
@@ -204,18 +198,10 @@ public abstract class NiFiProperties {
     // expression language properties
     public static final String VARIABLE_REGISTRY_PROPERTIES = "nifi.variable.registry.properties";
 
-    // build info
-    public static final String BUILD_TAG = "nifi.build.tag";
-    public static final String BUILD_BRANCH = "nifi.build.branch";
-    public static final String BUILD_REVISION = "nifi.build.revision";
-    public static final String BUILD_TIMESTAMP = "nifi.build.timestamp";
-
     // defaults
-    public static final String DEFAULT_TITLE = "NiFi";
     public static final Boolean DEFAULT_AUTO_RESUME_STATE = true;
     public static final String DEFAULT_AUTHORIZER_CONFIGURATION_FILE = "conf/authorizers.xml";
     public static final String DEFAULT_LOGIN_IDENTITY_PROVIDER_CONFIGURATION_FILE = "conf/login-identity-providers.xml";
-    public static final String DEFAULT_USER_CREDENTIAL_CACHE_DURATION = "24 hours";
     public static final Integer DEFAULT_REMOTE_INPUT_PORT = null;
     public static final Path DEFAULT_TEMPLATE_DIRECTORY = Paths.get("conf", "templates");
     public static final int DEFAULT_WEB_THREADS = 200;
@@ -612,14 +598,6 @@ public abstract class NiFiProperties {
     }
 
     // getters for ui properties //
-    /**
-     * Get the title for the UI.
-     *
-     * @return The UI title
-     */
-    public String getUiTitle() {
-        return this.getProperty(VERSION, DEFAULT_TITLE);
-    }
 
     /**
      * Get the banner text.
@@ -1008,21 +986,6 @@ public abstract class NiFiProperties {
         }
     }
 
-    public Date getBuildTimestamp() {
-        String buildTimestampString = getProperty(NiFiProperties.BUILD_TIMESTAMP);
-        if (!StringUtils.isEmpty(buildTimestampString)) {
-            try {
-                SimpleDateFormat buildTimestampFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
-                Date buildTimestampDate = buildTimestampFormat.parse(buildTimestampString);
-                return buildTimestampDate;
-            } catch (ParseException parseEx) {
-                return null;
-            }
-        } else {
-            return null;
-        }
-    }
-
     /**
      * Returns the network interface list to use for HTTP. This method returns a mapping of
      * network interface property names to network interface names.

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-commons/nifi-properties/src/test/resources/NiFiProperties/conf/nifi.blank.properties
----------------------------------------------------------------------
diff --git a/nifi-commons/nifi-properties/src/test/resources/NiFiProperties/conf/nifi.blank.properties b/nifi-commons/nifi-properties/src/test/resources/NiFiProperties/conf/nifi.blank.properties
index 898cebf..aaf2e29 100644
--- a/nifi-commons/nifi-properties/src/test/resources/NiFiProperties/conf/nifi.blank.properties
+++ b/nifi-commons/nifi-properties/src/test/resources/NiFiProperties/conf/nifi.blank.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-commons/nifi-properties/src/test/resources/NiFiProperties/conf/nifi.missing.properties
----------------------------------------------------------------------
diff --git a/nifi-commons/nifi-properties/src/test/resources/NiFiProperties/conf/nifi.missing.properties b/nifi-commons/nifi-properties/src/test/resources/NiFiProperties/conf/nifi.missing.properties
index 786b05f..fb48be3 100644
--- a/nifi-commons/nifi-properties/src/test/resources/NiFiProperties/conf/nifi.missing.properties
+++ b/nifi-commons/nifi-properties/src/test/resources/NiFiProperties/conf/nifi.missing.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-commons/nifi-properties/src/test/resources/NiFiProperties/conf/nifi.properties
----------------------------------------------------------------------
diff --git a/nifi-commons/nifi-properties/src/test/resources/NiFiProperties/conf/nifi.properties b/nifi-commons/nifi-properties/src/test/resources/NiFiProperties/conf/nifi.properties
index f9d9b78..6d1e03b 100644
--- a/nifi-commons/nifi-properties/src/test/resources/NiFiProperties/conf/nifi.properties
+++ b/nifi-commons/nifi-properties/src/test/resources/NiFiProperties/conf/nifi.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-docs/src/main/asciidoc/administration-guide.adoc
----------------------------------------------------------------------
diff --git a/nifi-docs/src/main/asciidoc/administration-guide.adoc b/nifi-docs/src/main/asciidoc/administration-guide.adoc
index ca8f6a0..d3abd3a 100644
--- a/nifi-docs/src/main/asciidoc/administration-guide.adoc
+++ b/nifi-docs/src/main/asciidoc/administration-guide.adoc
@@ -1928,7 +1928,6 @@ The first section of the _nifi.properties_ file is for the Core Properties. Thes
 
 |===
 |*Property*|*Description*
-|nifi.version|The version number of the current release. If upgrading but reusing this file, be sure to update this value.
 |nifi.flow.configuration.file*|The location of the flow configuration file (i.e., the file that contains what is currently displayed on the NiFi graph). The default value is ./conf/flow.xml.gz.
 |nifi.flow.configuration.archive.enabled*|Specifies whether NiFi creates a backup copy of the flow automatically when the flow is updated. The default value is _true_.
 |nifi.flow.configuration.archive.dir*|The location of the archive directory where backup copies of the flow.xml are saved. The default value is ./conf/archive. NiFi removes old archive files to limit disk usage based on archived file lifespan, total size, and number of files, as specified with nifi.flow.configuration.archive.max.time, max.storage and max.count properties respectively. If none of these limitation for archiving is specified, NiFi uses default condition, that is "30 days" for max.time and "500 MB" for max.storage. +

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-docs/src/main/asciidoc/developer-guide.adoc
----------------------------------------------------------------------
diff --git a/nifi-docs/src/main/asciidoc/developer-guide.adoc b/nifi-docs/src/main/asciidoc/developer-guide.adoc
index 4dbe649..429bd2c 100644
--- a/nifi-docs/src/main/asciidoc/developer-guide.adoc
+++ b/nifi-docs/src/main/asciidoc/developer-guide.adoc
@@ -2362,6 +2362,16 @@ component, use this capability judiciously. If ten instances of one component ar
 from the component's NAR ClassLoader are loaded into memory ten times. This could eventually increase the
 memory footprint significantly when enough instances of the component are created.
 
+Additionally, there are some restrictions when using @RequiresInstanceClassLoading when using Controller
+Services. Processors, Reporting Tasks, and Controller Services can reference a Controller Service API
+in one of its Property Descriptors. An issue may arise when the Controller Service API is bundled in the same
+NAR with a component that references it or with the Controller Service implementation. If either of these cases
+are encountered and the extension requires instance classloading, the extension will be skipped and an appropriate
+ERROR will be logged. To address this issue, the Controller Service API should be bundled in a parent NAR. The
+service implementation and extensions that reference that service should depend on the Controller Service API NAR.
+Please refer to the Controller Service NAR Layout in the <<nars>> section. Anytime a Controller Service API is
+bundled with an extension that requires it, even if @RequiresInstanceClassLoading isn't used, a WARNING will be
+logged to help avoid this bad practice.
 
 
 == How to contribute to Apache NiFi

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-framework-api/src/main/java/org/apache/nifi/bundle/Bundle.java
----------------------------------------------------------------------
diff --git a/nifi-framework-api/src/main/java/org/apache/nifi/bundle/Bundle.java b/nifi-framework-api/src/main/java/org/apache/nifi/bundle/Bundle.java
new file mode 100644
index 0000000..f8290cb
--- /dev/null
+++ b/nifi-framework-api/src/main/java/org/apache/nifi/bundle/Bundle.java
@@ -0,0 +1,48 @@
+/*
+ * 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.bundle;
+
+/**
+ * Represents a bundle that contains one or more extensions.
+ */
+public class Bundle {
+
+    private final BundleDetails bundleDetails;
+
+    private final ClassLoader classLoader;
+
+    public Bundle(final BundleDetails bundleDetails, final ClassLoader classLoader) {
+        this.bundleDetails = bundleDetails;
+        this.classLoader = classLoader;
+
+        if (this.bundleDetails == null) {
+            throw new IllegalStateException("BundleDetails cannot be null");
+        }
+
+        if (this.classLoader == null) {
+            throw new IllegalStateException("ClassLoader cannot be null");
+        }
+    }
+
+    public BundleDetails getBundleDetails() {
+        return bundleDetails;
+    }
+
+    public ClassLoader getClassLoader() {
+        return classLoader;
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-framework-api/src/main/java/org/apache/nifi/bundle/BundleCoordinate.java
----------------------------------------------------------------------
diff --git a/nifi-framework-api/src/main/java/org/apache/nifi/bundle/BundleCoordinate.java b/nifi-framework-api/src/main/java/org/apache/nifi/bundle/BundleCoordinate.java
new file mode 100644
index 0000000..efb0d48
--- /dev/null
+++ b/nifi-framework-api/src/main/java/org/apache/nifi/bundle/BundleCoordinate.java
@@ -0,0 +1,90 @@
+/*
+ * 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.bundle;
+
+/**
+ * The coordinates of a bundle (group, artifact, version).
+ */
+public class BundleCoordinate {
+
+    public static final String DEFAULT_GROUP = "default";
+    public static final String DEFAULT_VERSION = "unversioned";
+
+    public static final BundleCoordinate UNKNOWN_COORDINATE = new BundleCoordinate(DEFAULT_GROUP, "unknown", DEFAULT_VERSION);
+
+    private final String group;
+    private final String id;
+    private final String version;
+    private final String coordinate;
+
+    public BundleCoordinate(final String group, final String id, final String version) {
+        this.group = isBlank(group) ? DEFAULT_GROUP : group;
+        this.id = id;
+        this.version = isBlank(version) ? DEFAULT_VERSION : version;
+
+        if (isBlank(id)) {
+            throw new IllegalStateException("Id is required for BundleCoordinate");
+        }
+
+        this.coordinate = this.group + ":" + this.id + ":" + this.version;
+    }
+
+    private boolean isBlank(String str) {
+        return str == null || str.trim().length() == 0;
+    }
+
+    public String getGroup() {
+        return group;
+    }
+
+    public String getId() {
+        return id;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public final String getCoordinate() {
+        return coordinate;
+    }
+
+    @Override
+    public String toString() {
+        return coordinate;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (obj == null) {
+            return false;
+        }
+
+        if (!(obj instanceof BundleCoordinate)) {
+            return false;
+        }
+
+        final BundleCoordinate other = (BundleCoordinate) obj;
+        return getCoordinate().equals(other.getCoordinate());
+    }
+
+    @Override
+    public int hashCode() {
+        return 37 * this.coordinate.hashCode();
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-framework-api/src/main/java/org/apache/nifi/bundle/BundleDetails.java
----------------------------------------------------------------------
diff --git a/nifi-framework-api/src/main/java/org/apache/nifi/bundle/BundleDetails.java b/nifi-framework-api/src/main/java/org/apache/nifi/bundle/BundleDetails.java
new file mode 100644
index 0000000..c1f2117
--- /dev/null
+++ b/nifi-framework-api/src/main/java/org/apache/nifi/bundle/BundleDetails.java
@@ -0,0 +1,188 @@
+/*
+ * 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.bundle;
+
+import java.io.File;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * Metadata about a bundle.
+ */
+public class BundleDetails {
+
+    private final File workingDirectory;
+
+    private final BundleCoordinate coordinate;
+    private final BundleCoordinate dependencyCoordinate;
+
+    private final String buildTag;
+    private final String buildRevision;
+    private final String buildBranch;
+    private final String buildTimestamp;
+    private final String buildJdk;
+    private final String builtBy;
+
+    private BundleDetails(final Builder builder) {
+        this.workingDirectory = builder.workingDirectory;
+        this.coordinate = builder.coordinate;
+        this.dependencyCoordinate = builder.dependencyCoordinate;
+
+        this.buildTag = builder.buildTag;
+        this.buildRevision = builder.buildRevision;
+        this.buildBranch = builder.buildBranch;
+        this.buildTimestamp = builder.buildTimestamp;
+        this.buildJdk = builder.buildJdk;
+        this.builtBy = builder.builtBy;
+
+        if (this.coordinate == null) {
+            if (this.workingDirectory == null) {
+                throw new IllegalStateException("Coordinate cannot be null");
+            } else {
+                throw new IllegalStateException("Coordinate cannot be null for " + this.workingDirectory.getAbsolutePath());
+            }
+        }
+
+        if (this.workingDirectory == null) {
+            throw new IllegalStateException("Working directory cannot be null for " + this.coordinate.getId());
+        }
+    }
+
+    public File getWorkingDirectory() {
+        return workingDirectory;
+    }
+
+    public BundleCoordinate getCoordinate() {
+        return coordinate;
+    }
+
+    public BundleCoordinate getDependencyCoordinate() {
+        return dependencyCoordinate;
+    }
+
+    public String getBuildTag() {
+        return buildTag;
+    }
+
+    public String getBuildRevision() {
+        return buildRevision;
+    }
+
+    public String getBuildBranch() {
+        return buildBranch;
+    }
+
+    public String getBuildTimestamp() {
+        return buildTimestamp;
+    }
+
+    public String getBuildJdk() {
+        return buildJdk;
+    }
+
+    public String getBuiltBy() {
+        return builtBy;
+    }
+
+    @Override
+    public String toString() {
+        return coordinate.toString();
+    }
+
+    public Date getBuildTimestampDate() {
+        if (buildTimestamp != null && !buildTimestamp.isEmpty()) {
+            try {
+                SimpleDateFormat buildTimestampFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
+                Date buildTimestampDate = buildTimestampFormat.parse(buildTimestamp);
+                return buildTimestampDate;
+            } catch (ParseException parseEx) {
+                return null;
+            }
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Builder for NarDetails.
+     */
+    public static class Builder {
+
+        private File workingDirectory;
+
+        private BundleCoordinate coordinate;
+        private BundleCoordinate dependencyCoordinate;
+
+        private String buildTag;
+        private String buildRevision;
+        private String buildBranch;
+        private String buildTimestamp;
+        private String buildJdk;
+        private String builtBy;
+
+        public Builder workingDir(final File workingDirectory) {
+            this.workingDirectory = workingDirectory;
+            return this;
+        }
+
+        public Builder coordinate(final BundleCoordinate coordinate) {
+            this.coordinate = coordinate;
+            return this;
+        }
+
+        public Builder dependencyCoordinate(final BundleCoordinate dependencyCoordinate) {
+            this.dependencyCoordinate = dependencyCoordinate;
+            return this;
+        }
+
+        public Builder buildTag(final String buildTag) {
+            this.buildTag = buildTag;
+            return this;
+        }
+
+        public Builder buildRevision(final String buildRevision) {
+            this.buildRevision = buildRevision;
+            return this;
+        }
+
+        public Builder buildBranch(final String buildBranch) {
+            this.buildBranch = buildBranch;
+            return this;
+        }
+
+        public Builder buildTimestamp(final String buildTimestamp) {
+            this.buildTimestamp = buildTimestamp;
+            return this;
+        }
+
+        public Builder buildJdk(final String buildJdk) {
+            this.buildJdk = buildJdk;
+            return this;
+        }
+
+        public Builder builtBy(final String builtBy) {
+            this.builtBy = builtBy;
+            return this;
+        }
+
+        public BundleDetails build() {
+            return new BundleDetails(this);
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-framework-api/src/main/java/org/apache/nifi/components/state/StateProviderInitializationContext.java
----------------------------------------------------------------------
diff --git a/nifi-framework-api/src/main/java/org/apache/nifi/components/state/StateProviderInitializationContext.java b/nifi-framework-api/src/main/java/org/apache/nifi/components/state/StateProviderInitializationContext.java
index aaf5490..4182490 100644
--- a/nifi-framework-api/src/main/java/org/apache/nifi/components/state/StateProviderInitializationContext.java
+++ b/nifi-framework-api/src/main/java/org/apache/nifi/components/state/StateProviderInitializationContext.java
@@ -23,6 +23,7 @@ import javax.net.ssl.SSLContext;
 
 import org.apache.nifi.components.PropertyDescriptor;
 import org.apache.nifi.components.PropertyValue;
+import org.apache.nifi.logging.ComponentLog;
 
 /**
  * This interface defines an initialization context that is passed to a {@link StateProvider} when it
@@ -53,4 +54,10 @@ public interface StateProviderInitializationContext {
      *         or <code>null</code> if no SSLContext has been configured
      */
     SSLContext getSSLContext();
+
+    /**
+     * @return the logger for the given state provider
+     */
+    ComponentLog getLogger();
+
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-framework-api/src/test/java/org/apache/nifi/bundle/BundleCoordinateTest.java
----------------------------------------------------------------------
diff --git a/nifi-framework-api/src/test/java/org/apache/nifi/bundle/BundleCoordinateTest.java b/nifi-framework-api/src/test/java/org/apache/nifi/bundle/BundleCoordinateTest.java
new file mode 100644
index 0000000..20e1d75
--- /dev/null
+++ b/nifi-framework-api/src/test/java/org/apache/nifi/bundle/BundleCoordinateTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.bundle;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class BundleCoordinateTest {
+
+    @Test
+    public void testConstructorAndEquals() {
+        final String group = "group1";
+        final String id = "id1";
+        final String version = "v1";
+
+        final BundleCoordinate coordinate = new BundleCoordinate(group, id, version);
+        assertEquals(group, coordinate.getGroup());
+        assertEquals(id, coordinate.getId());
+        assertEquals(version, coordinate.getVersion());
+        assertEquals(group + ":" + id + ":" + version, coordinate.getCoordinate());
+
+        final BundleCoordinate coordinate2 = new BundleCoordinate(group, id, version);
+        assertEquals(coordinate, coordinate2);
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testIdRequired() {
+        final String group = "group1";
+        final String id = null;
+        final String version = "v1";
+        new BundleCoordinate(group, id, version);
+    }
+
+    @Test
+    public void testDefaultGroup() {
+        final String group = null;
+        final String id = "id1";
+        final String version = "v1";
+
+        final BundleCoordinate coordinate = new BundleCoordinate(group, id, version);
+        assertEquals(BundleCoordinate.DEFAULT_GROUP, coordinate.getGroup());
+        assertEquals(id, coordinate.getId());
+        assertEquals(version, coordinate.getVersion());
+        assertEquals(BundleCoordinate.DEFAULT_GROUP + ":" + id + ":" + version, coordinate.getCoordinate());
+    }
+
+    @Test
+    public void testVersionRequired() {
+        final String group = "group1";
+        final String id = "id1";
+        final String version = null;
+
+        final BundleCoordinate coordinate = new BundleCoordinate(group, id, version);
+        assertEquals(group, coordinate.getGroup());
+        assertEquals(id, coordinate.getId());
+        assertEquals(BundleCoordinate.DEFAULT_VERSION, coordinate.getVersion());
+        assertEquals(group + ":" + id + ":" + BundleCoordinate.DEFAULT_VERSION, coordinate.getCoordinate());
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-framework-api/src/test/java/org/apache/nifi/bundle/BundleDetailsTest.java
----------------------------------------------------------------------
diff --git a/nifi-framework-api/src/test/java/org/apache/nifi/bundle/BundleDetailsTest.java b/nifi-framework-api/src/test/java/org/apache/nifi/bundle/BundleDetailsTest.java
new file mode 100644
index 0000000..e2475b6
--- /dev/null
+++ b/nifi-framework-api/src/test/java/org/apache/nifi/bundle/BundleDetailsTest.java
@@ -0,0 +1,151 @@
+/*
+ * 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.bundle;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+import java.io.File;
+
+public class BundleDetailsTest {
+
+    @Test
+    public void testBuilder() {
+        final File workingDirectory = new File("src/test/resources");
+
+        final BundleCoordinate coordinate = new BundleCoordinate("org.apache.nifi", "nifi-hadoop-nar", "1.0.0");
+        final BundleCoordinate dependencyCoordinate = new BundleCoordinate("org.apache.nifi", "nifi-hadoop-libraries-nar", "1.0.0");
+
+        final String buildTag = "HEAD";
+        final String buildRevision = "1";
+        final String buildBranch = "DEV";
+        final String buildTimestamp = "2017-01-01 00:00:00";
+        final String buildJdk = "JDK8";
+        final String builtBy = "bbende";
+
+        final BundleDetails bundleDetails = new BundleDetails.Builder()
+                .workingDir(workingDirectory)
+                .coordinate(coordinate)
+                .dependencyCoordinate(dependencyCoordinate)
+                .buildTag(buildTag)
+                .buildRevision(buildRevision)
+                .buildBranch(buildBranch)
+                .buildTimestamp(buildTimestamp)
+                .buildJdk(buildJdk)
+                .builtBy(builtBy)
+                .build();
+
+        assertEquals(workingDirectory, bundleDetails.getWorkingDirectory());
+        assertEquals(coordinate, bundleDetails.getCoordinate());
+        assertEquals(dependencyCoordinate, bundleDetails.getDependencyCoordinate());
+        assertEquals(buildTag, bundleDetails.getBuildTag());
+        assertEquals(buildRevision, bundleDetails.getBuildRevision());
+        assertEquals(buildBranch, bundleDetails.getBuildBranch());
+        assertEquals(buildTimestamp, bundleDetails.getBuildTimestamp());
+        assertEquals(buildJdk, bundleDetails.getBuildJdk());
+        assertEquals(builtBy, bundleDetails.getBuiltBy());
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testWorkingDirRequired() {
+        final BundleCoordinate coordinate = new BundleCoordinate("org.apache.nifi", "nifi-hadoop-nar", "1.0.0");
+        final BundleCoordinate dependencyCoordinate = new BundleCoordinate("org.apache.nifi", "nifi-hadoop-libraries-nar", "1.0.0");
+
+        final String buildTag = "HEAD";
+        final String buildRevision = "1";
+        final String buildBranch = "DEV";
+        final String buildTimestamp = "2017-01-01 00:00:00";
+        final String buildJdk = "JDK8";
+        final String builtBy = "bbende";
+
+        new BundleDetails.Builder()
+                .workingDir(null)
+                .coordinate(coordinate)
+                .dependencyCoordinate(dependencyCoordinate)
+                .buildTag(buildTag)
+                .buildRevision(buildRevision)
+                .buildBranch(buildBranch)
+                .buildTimestamp(buildTimestamp)
+                .buildJdk(buildJdk)
+                .builtBy(builtBy)
+                .build();
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testCoordinateRequired() {
+        final File workingDirectory = new File("src/test/resources");
+        final BundleCoordinate dependencyCoordinate = new BundleCoordinate("org.apache.nifi", "nifi-hadoop-libraries-nar", "1.0.0");
+
+        final String buildTag = "HEAD";
+        final String buildRevision = "1";
+        final String buildBranch = "DEV";
+        final String buildTimestamp = "2017-01-01 00:00:00";
+        final String buildJdk = "JDK8";
+        final String builtBy = "bbende";
+
+        new BundleDetails.Builder()
+                .workingDir(workingDirectory)
+                .coordinate(null)
+                .dependencyCoordinate(dependencyCoordinate)
+                .buildTag(buildTag)
+                .buildRevision(buildRevision)
+                .buildBranch(buildBranch)
+                .buildTimestamp(buildTimestamp)
+                .buildJdk(buildJdk)
+                .builtBy(builtBy)
+                .build();
+    }
+
+    @Test
+    public void testDependencyCoordinateCanBeNull() {
+        final File workingDirectory = new File("src/test/resources");
+
+        final BundleCoordinate coordinate = new BundleCoordinate("org.apache.nifi", "nifi-hadoop-nar", "1.0.0");
+        final BundleCoordinate dependencyCoordinate = null;
+
+        final String buildTag = "HEAD";
+        final String buildRevision = "1";
+        final String buildBranch = "DEV";
+        final String buildTimestamp = "2017-01-01 00:00:00";
+        final String buildJdk = "JDK8";
+        final String builtBy = "bbende";
+
+        final BundleDetails bundleDetails = new BundleDetails.Builder()
+                .workingDir(workingDirectory)
+                .coordinate(coordinate)
+                .dependencyCoordinate(dependencyCoordinate)
+                .buildTag(buildTag)
+                .buildRevision(buildRevision)
+                .buildBranch(buildBranch)
+                .buildTimestamp(buildTimestamp)
+                .buildJdk(buildJdk)
+                .builtBy(builtBy)
+                .build();
+
+        assertEquals(workingDirectory, bundleDetails.getWorkingDirectory());
+        assertEquals(coordinate, bundleDetails.getCoordinate());
+        assertEquals(dependencyCoordinate, bundleDetails.getDependencyCoordinate());
+        assertEquals(buildTag, bundleDetails.getBuildTag());
+        assertEquals(buildRevision, bundleDetails.getBuildRevision());
+        assertEquals(buildBranch, bundleDetails.getBuildBranch());
+        assertEquals(buildTimestamp, bundleDetails.getBuildTimestamp());
+        assertEquals(buildJdk, bundleDetails.getBuildJdk());
+        assertEquals(builtBy, bundleDetails.getBuiltBy());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-mock/src/main/resources/META-INF/services/org.apache.nifi.provenance.ProvenanceRepository
----------------------------------------------------------------------
diff --git a/nifi-mock/src/main/resources/META-INF/services/org.apache.nifi.provenance.ProvenanceRepository b/nifi-mock/src/main/resources/META-INF/services/org.apache.nifi.provenance.ProvenanceRepository
new file mode 100644
index 0000000..8414f9e
--- /dev/null
+++ b/nifi-mock/src/main/resources/META-INF/services/org.apache.nifi.provenance.ProvenanceRepository
@@ -0,0 +1,15 @@
+# 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.provenance.MockProvenanceRepository
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-ambari-bundle/nifi-ambari-reporting-task/src/main/resources/docs/org.apache.nifi.reporting.ambari.AmbariReportingTask/additionalDetails.html
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-ambari-bundle/nifi-ambari-reporting-task/src/main/resources/docs/org.apache.nifi.reporting.ambari.AmbariReportingTask/additionalDetails.html b/nifi-nar-bundles/nifi-ambari-bundle/nifi-ambari-reporting-task/src/main/resources/docs/org.apache.nifi.reporting.ambari.AmbariReportingTask/additionalDetails.html
index 707de6e..3c04cd4 100644
--- a/nifi-nar-bundles/nifi-ambari-bundle/nifi-ambari-reporting-task/src/main/resources/docs/org.apache.nifi.reporting.ambari.AmbariReportingTask/additionalDetails.html
+++ b/nifi-nar-bundles/nifi-ambari-bundle/nifi-ambari-reporting-task/src/main/resources/docs/org.apache.nifi.reporting.ambari.AmbariReportingTask/additionalDetails.html
@@ -17,7 +17,7 @@
     <head>
         <meta charset="utf-8" />
         <title>AmbariReportingTask</title>
-        <link rel="stylesheet" href="../../css/component-usage.css" type="text/css" />
+        <link rel="stylesheet" href="/nifi-docs/css/component-usage.css" type="text/css" />
     </head>
 
     <body>

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-amqp-bundle/nifi-amqp-processors/src/main/resources/docs/org.apache.nifi.amqp.processors.ConsumeAMQP/additionalDetails.html
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-amqp-bundle/nifi-amqp-processors/src/main/resources/docs/org.apache.nifi.amqp.processors.ConsumeAMQP/additionalDetails.html b/nifi-nar-bundles/nifi-amqp-bundle/nifi-amqp-processors/src/main/resources/docs/org.apache.nifi.amqp.processors.ConsumeAMQP/additionalDetails.html
index bb342ce..a7c0f79 100644
--- a/nifi-nar-bundles/nifi-amqp-bundle/nifi-amqp-processors/src/main/resources/docs/org.apache.nifi.amqp.processors.ConsumeAMQP/additionalDetails.html
+++ b/nifi-nar-bundles/nifi-amqp-bundle/nifi-amqp-processors/src/main/resources/docs/org.apache.nifi.amqp.processors.ConsumeAMQP/additionalDetails.html
@@ -17,7 +17,7 @@
 <head>
     <meta charset="utf-8" />
     <title>ConsumeAMQP</title>
-    <link rel="stylesheet" href="../../css/component-usage.css" type="text/css" />
+    <link rel="stylesheet" href="/nifi-docs/css/component-usage.css" type="text/css" />
 </head>
 
 <body>

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-amqp-bundle/nifi-amqp-processors/src/main/resources/docs/org.apache.nifi.amqp.processors.PublishAMQP/additionalDetails.html
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-amqp-bundle/nifi-amqp-processors/src/main/resources/docs/org.apache.nifi.amqp.processors.PublishAMQP/additionalDetails.html b/nifi-nar-bundles/nifi-amqp-bundle/nifi-amqp-processors/src/main/resources/docs/org.apache.nifi.amqp.processors.PublishAMQP/additionalDetails.html
index 8aa9a32..1c8ccc6 100644
--- a/nifi-nar-bundles/nifi-amqp-bundle/nifi-amqp-processors/src/main/resources/docs/org.apache.nifi.amqp.processors.PublishAMQP/additionalDetails.html
+++ b/nifi-nar-bundles/nifi-amqp-bundle/nifi-amqp-processors/src/main/resources/docs/org.apache.nifi.amqp.processors.PublishAMQP/additionalDetails.html
@@ -17,7 +17,7 @@
 <head>
     <meta charset="utf-8" />
     <title>PublishAMQP</title>
-    <link rel="stylesheet" href="../../css/component-usage.css" type="text/css" />
+    <link rel="stylesheet" href="/nifi-docs/css/component-usage.css" type="text/css" />
 </head>
 
 <body>

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-datadog-bundle/nifi-datadog-reporting-task/src/main/resources/docs/org.apache.nifi.reporting.datadog.DataDogReportingTask/additionalDetails.html
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-datadog-bundle/nifi-datadog-reporting-task/src/main/resources/docs/org.apache.nifi.reporting.datadog.DataDogReportingTask/additionalDetails.html b/nifi-nar-bundles/nifi-datadog-bundle/nifi-datadog-reporting-task/src/main/resources/docs/org.apache.nifi.reporting.datadog.DataDogReportingTask/additionalDetails.html
index 8858562..9731226 100644
--- a/nifi-nar-bundles/nifi-datadog-bundle/nifi-datadog-reporting-task/src/main/resources/docs/org.apache.nifi.reporting.datadog.DataDogReportingTask/additionalDetails.html
+++ b/nifi-nar-bundles/nifi-datadog-bundle/nifi-datadog-reporting-task/src/main/resources/docs/org.apache.nifi.reporting.datadog.DataDogReportingTask/additionalDetails.html
@@ -17,7 +17,7 @@
     <head>
         <meta charset="utf-8" />
         <title>DataDogReportingTask</title>
-        <link rel="stylesheet" href="../../css/component-usage.css" type="text/css" />
+        <link rel="stylesheet" href="/nifi-docs/css/component-usage.css" type="text/css" />
     </head>
 
     <body>

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-email-bundle/nifi-email-processors/src/main/resources/docs/org.apache.nifi.processors.email.ConsumeIMAP/additionalDetails.html
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-email-bundle/nifi-email-processors/src/main/resources/docs/org.apache.nifi.processors.email.ConsumeIMAP/additionalDetails.html b/nifi-nar-bundles/nifi-email-bundle/nifi-email-processors/src/main/resources/docs/org.apache.nifi.processors.email.ConsumeIMAP/additionalDetails.html
index 3be9a84..64f0949 100644
--- a/nifi-nar-bundles/nifi-email-bundle/nifi-email-processors/src/main/resources/docs/org.apache.nifi.processors.email.ConsumeIMAP/additionalDetails.html
+++ b/nifi-nar-bundles/nifi-email-bundle/nifi-email-processors/src/main/resources/docs/org.apache.nifi.processors.email.ConsumeIMAP/additionalDetails.html
@@ -17,7 +17,7 @@
 <head>
 <meta charset="utf-8" />
 <title>ConsumeIMAP</title>
-<link rel="stylesheet" href="../../css/component-usage.css"
+<link rel="stylesheet" href="/nifi-docs/css/component-usage.css"
 	type="text/css" />
 </head>
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-email-bundle/nifi-email-processors/src/main/resources/docs/org.apache.nifi.processors.email.ConsumePOP3/additionalDetails.html
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-email-bundle/nifi-email-processors/src/main/resources/docs/org.apache.nifi.processors.email.ConsumePOP3/additionalDetails.html b/nifi-nar-bundles/nifi-email-bundle/nifi-email-processors/src/main/resources/docs/org.apache.nifi.processors.email.ConsumePOP3/additionalDetails.html
index 55a2220..0c553ad 100644
--- a/nifi-nar-bundles/nifi-email-bundle/nifi-email-processors/src/main/resources/docs/org.apache.nifi.processors.email.ConsumePOP3/additionalDetails.html
+++ b/nifi-nar-bundles/nifi-email-bundle/nifi-email-processors/src/main/resources/docs/org.apache.nifi.processors.email.ConsumePOP3/additionalDetails.html
@@ -17,7 +17,7 @@
 <head>
 <meta charset="utf-8" />
 <title>ConsumePOP3</title>
-<link rel="stylesheet" href="../../css/component-usage.css"
+<link rel="stylesheet" href="/nifi-docs/css/component-usage.css"
 	type="text/css" />
 </head>
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/resources/docs/org.apache.nifi.processors.evtx.ParseEvtx/additionalDetails.html
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/resources/docs/org.apache.nifi.processors.evtx.ParseEvtx/additionalDetails.html b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/resources/docs/org.apache.nifi.processors.evtx.ParseEvtx/additionalDetails.html
index faa5baa..8a62ea4 100644
--- a/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/resources/docs/org.apache.nifi.processors.evtx.ParseEvtx/additionalDetails.html
+++ b/nifi-nar-bundles/nifi-evtx-bundle/nifi-evtx-processors/src/main/resources/docs/org.apache.nifi.processors.evtx.ParseEvtx/additionalDetails.html
@@ -18,7 +18,7 @@
         <meta charset="utf-8" />
         <title>ParseEvtx</title>
 
-        <link rel="stylesheet" href="../../css/component-usage.css" type="text/css" />
+        <link rel="stylesheet" href="/nifi-docs/css/component-usage.css" type="text/css" />
     </head>
 
     <body>

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-flume-bundle/nifi-flume-processors/src/main/resources/docs/org.apache.nifi.processors.flume.ExecuteFlumeSink/additionalDetails.html
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-flume-bundle/nifi-flume-processors/src/main/resources/docs/org.apache.nifi.processors.flume.ExecuteFlumeSink/additionalDetails.html b/nifi-nar-bundles/nifi-flume-bundle/nifi-flume-processors/src/main/resources/docs/org.apache.nifi.processors.flume.ExecuteFlumeSink/additionalDetails.html
index 56e9e99..9455ef6 100644
--- a/nifi-nar-bundles/nifi-flume-bundle/nifi-flume-processors/src/main/resources/docs/org.apache.nifi.processors.flume.ExecuteFlumeSink/additionalDetails.html
+++ b/nifi-nar-bundles/nifi-flume-bundle/nifi-flume-processors/src/main/resources/docs/org.apache.nifi.processors.flume.ExecuteFlumeSink/additionalDetails.html
@@ -17,7 +17,7 @@
 <head>
     <meta charset="utf-8" />
     <title>ExecuteFlumeSink</title>
-    <link rel="stylesheet" href="../../css/component-usage.css" type="text/css" />
+    <link rel="stylesheet" href="/nifi-docs/css/component-usage.css" type="text/css" />
 </head>
 
 <body>

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-flume-bundle/nifi-flume-processors/src/main/resources/docs/org.apache.nifi.processors.flume.ExecuteFlumeSource/additionalDetails.html
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-flume-bundle/nifi-flume-processors/src/main/resources/docs/org.apache.nifi.processors.flume.ExecuteFlumeSource/additionalDetails.html b/nifi-nar-bundles/nifi-flume-bundle/nifi-flume-processors/src/main/resources/docs/org.apache.nifi.processors.flume.ExecuteFlumeSource/additionalDetails.html
index 3d1062b..d1c76b2 100644
--- a/nifi-nar-bundles/nifi-flume-bundle/nifi-flume-processors/src/main/resources/docs/org.apache.nifi.processors.flume.ExecuteFlumeSource/additionalDetails.html
+++ b/nifi-nar-bundles/nifi-flume-bundle/nifi-flume-processors/src/main/resources/docs/org.apache.nifi.processors.flume.ExecuteFlumeSource/additionalDetails.html
@@ -17,7 +17,7 @@
 <head>
     <meta charset="utf-8" />
     <title>ExecuteFlumeSource</title>
-    <link rel="stylesheet" href="../../css/component-usage.css" type="text/css" />
+    <link rel="stylesheet" href="/nifi-docs/css/component-usage.css" type="text/css" />
 </head>
 
 <body>

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework-nar/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework-nar/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework-nar/pom.xml
index e4a0df7..a812a6f 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework-nar/pom.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework-nar/pom.xml
@@ -39,6 +39,10 @@
             <groupId>org.apache.nifi</groupId>
             <artifactId>nifi-authorizer</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-standard-prioritizers</artifactId>
+        </dependency>
 
         <!-- mark these nifi artifacts as provided since it is included in the lib -->
         <dependency>

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-authorizer/src/main/java/org/apache/nifi/authorization/AuthorizerFactoryBean.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-authorizer/src/main/java/org/apache/nifi/authorization/AuthorizerFactoryBean.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-authorizer/src/main/java/org/apache/nifi/authorization/AuthorizerFactoryBean.java
index ba8866d..b934cb8 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-authorizer/src/main/java/org/apache/nifi/authorization/AuthorizerFactoryBean.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-authorizer/src/main/java/org/apache/nifi/authorization/AuthorizerFactoryBean.java
@@ -23,6 +23,7 @@ import org.apache.nifi.authorization.exception.AuthorizerCreationException;
 import org.apache.nifi.authorization.exception.AuthorizerDestructionException;
 import org.apache.nifi.authorization.generated.Authorizers;
 import org.apache.nifi.authorization.generated.Property;
+import org.apache.nifi.bundle.Bundle;
 import org.apache.nifi.nar.ExtensionManager;
 import org.apache.nifi.nar.NarCloseable;
 import org.apache.nifi.util.NiFiProperties;
@@ -46,6 +47,7 @@ import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
@@ -146,11 +148,19 @@ public class AuthorizerFactoryBean implements FactoryBean, DisposableBean, Autho
 
     private Authorizer createAuthorizer(final String identifier, final String authorizerClassName) throws Exception {
         // get the classloader for the specified authorizer
-        final ClassLoader authorizerClassLoader = ExtensionManager.getClassLoader(authorizerClassName);
-        if (authorizerClassLoader == null) {
+        final List<Bundle> authorizerBundles = ExtensionManager.getBundles(authorizerClassName);
+
+        if (authorizerBundles.size() == 0) {
             throw new Exception(String.format("The specified authorizer class '%s' is not known to this nifi.", authorizerClassName));
         }
 
+        if (authorizerBundles.size() > 1) {
+            throw new Exception(String.format("Multiple bundles found for the specified authorizer class '%s', only one is allowed.", authorizerClassName));
+        }
+
+        final Bundle authorizerBundle = authorizerBundles.get(0);
+        final ClassLoader authorizerClassLoader = authorizerBundle.getClassLoader();
+
         // get the current context classloader
         final ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader();
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/BundleDTO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/BundleDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/BundleDTO.java
new file mode 100644
index 0000000..de8231d
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/BundleDTO.java
@@ -0,0 +1,109 @@
+/*
+ * 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.web.api.dto;
+
+import com.wordnik.swagger.annotations.ApiModelProperty;
+
+import javax.xml.bind.annotation.XmlType;
+import java.util.Objects;
+
+/**
+ * Typed component within NiFi.
+ */
+@XmlType(name = "bundle")
+public class BundleDTO {
+
+    private String group;
+    private String artifact;
+    private String version;
+
+    public BundleDTO() {
+    }
+
+    public BundleDTO(final String group, final String artifact, final String version) {
+        this.group = group;
+        this.artifact = artifact;
+        this.version = version;
+    }
+
+    /**
+     * The group of the bundle.
+     *
+     * @return bundle group
+     */
+    @ApiModelProperty(
+            value = "The group of the bundle."
+    )
+    public String getGroup() {
+        return group;
+    }
+
+    public void setGroup(String group) {
+        this.group = group;
+    }
+
+    /**
+     * The artifact of the bundle.
+     *
+     * @return bundle artifact
+     */
+    @ApiModelProperty(
+            value = "The artifact of the bundle."
+    )
+    public String getArtifact() {
+        return artifact;
+    }
+
+    public void setArtifact(String artifact) {
+        this.artifact = artifact;
+    }
+
+    /**
+     * The version of the bundle.
+     *
+     * @return bundle version
+     */
+    @ApiModelProperty(
+            value = "The version of the bundle."
+    )
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        final BundleDTO bundleDTO = (BundleDTO) o;
+        return Objects.equals(group, bundleDTO.group) && Objects.equals(artifact, bundleDTO.artifact) && Objects.equals(version, bundleDTO.version);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(group, artifact, version);
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ControllerServiceApiDTO.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ControllerServiceApiDTO.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ControllerServiceApiDTO.java
new file mode 100644
index 0000000..63347fa
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-client-dto/src/main/java/org/apache/nifi/web/api/dto/ControllerServiceApiDTO.java
@@ -0,0 +1,81 @@
+/*
+ * 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.web.api.dto;
+
+import com.wordnik.swagger.annotations.ApiModelProperty;
+
+import javax.xml.bind.annotation.XmlType;
+import java.util.Objects;
+
+/**
+ * Class used for providing details of a Controller Service API.
+ */
+@XmlType(name = "controllerServiceApi")
+public class ControllerServiceApiDTO {
+
+    private String type;
+    private BundleDTO bundle;
+
+    /**
+     * @return The type is the fully-qualified name of the service interface
+     */
+    @ApiModelProperty(
+            value = "The fully qualified name of the service interface."
+    )
+    public String getType() {
+        return type;
+    }
+
+    public void setType(String type) {
+        this.type = type;
+    }
+
+    /**
+     * The details of the artifact that bundled this service interface.
+     *
+     * @return The bundle details
+     */
+    @ApiModelProperty(
+            value = "The details of the artifact that bundled this service interface."
+    )
+    public BundleDTO getBundle() {
+        return bundle;
+    }
+
+    public void setBundle(BundleDTO bundle) {
+        this.bundle = bundle;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+
+        if (o == null || getClass() != o.getClass()) {
+            return false;
+        }
+
+        final ControllerServiceApiDTO that = (ControllerServiceApiDTO) o;
+        return Objects.equals(type, that.type) && Objects.equals(bundle, that.bundle);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(type, bundle);
+    }
+}