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 2018/11/01 18:41:42 UTC
[4/7] nifi git commit: NIFI-5673 Set up property/assembly for new
auto-load directory - Set up NarAutoLoader to watch directory for new files -
Move NarAutoLoader to JettyServer since it will need access to
ExtensionManager - Created NarLoader to shared
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/scheduling/StandardProcessSchedulerIT.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/scheduling/StandardProcessSchedulerIT.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/scheduling/StandardProcessSchedulerIT.java
index f8a4b43..fac0272 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/scheduling/StandardProcessSchedulerIT.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/scheduling/StandardProcessSchedulerIT.java
@@ -17,12 +17,6 @@
package org.apache.nifi.controller.scheduling;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Collections;
-
import org.apache.nifi.bundle.Bundle;
import org.apache.nifi.components.state.StateManagerProvider;
import org.apache.nifi.controller.FlowController;
@@ -30,7 +24,8 @@ import org.apache.nifi.controller.service.ControllerServiceNode;
import org.apache.nifi.controller.service.ControllerServiceState;
import org.apache.nifi.controller.service.StandardControllerServiceProvider;
import org.apache.nifi.engine.FlowEngine;
-import org.apache.nifi.nar.ExtensionManager;
+import org.apache.nifi.nar.ExtensionDiscoveringManager;
+import org.apache.nifi.nar.StandardExtensionDiscoveringManager;
import org.apache.nifi.nar.SystemBundle;
import org.apache.nifi.registry.VariableRegistry;
import org.apache.nifi.reporting.InitializationException;
@@ -40,12 +35,19 @@ import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
+import java.util.Collections;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
public class StandardProcessSchedulerIT {
private final StateManagerProvider stateMgrProvider = Mockito.mock(StateManagerProvider.class);
private VariableRegistry variableRegistry = VariableRegistry.ENVIRONMENT_SYSTEM_REGISTRY;
private FlowController controller;
private NiFiProperties nifiProperties;
private Bundle systemBundle;
+ private ExtensionDiscoveringManager extensionManager;
private volatile String propsFile = TestStandardProcessScheduler.class.getResource("/standardprocessschedulertest.nifi.properties").getFile();
@Before
@@ -54,9 +56,11 @@ public class StandardProcessSchedulerIT {
// load the system bundle
systemBundle = SystemBundle.create(nifiProperties);
- ExtensionManager.discoverExtensions(systemBundle, Collections.emptySet());
+ extensionManager = new StandardExtensionDiscoveringManager();
+ extensionManager.discoverExtensions(systemBundle, Collections.emptySet());
controller = Mockito.mock(FlowController.class);
+ Mockito.when(controller.getExtensionManager()).thenReturn(extensionManager);
}
/**
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/scheduling/TestStandardProcessScheduler.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/scheduling/TestStandardProcessScheduler.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/scheduling/TestStandardProcessScheduler.java
index 3c382cf..92e6e5d 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/scheduling/TestStandardProcessScheduler.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/scheduling/TestStandardProcessScheduler.java
@@ -44,7 +44,8 @@ import org.apache.nifi.controller.service.mock.MockProcessGroup;
import org.apache.nifi.engine.FlowEngine;
import org.apache.nifi.groups.ProcessGroup;
import org.apache.nifi.logging.ComponentLog;
-import org.apache.nifi.nar.ExtensionManager;
+import org.apache.nifi.nar.ExtensionDiscoveringManager;
+import org.apache.nifi.nar.StandardExtensionDiscoveringManager;
import org.apache.nifi.nar.SystemBundle;
import org.apache.nifi.processor.AbstractProcessor;
import org.apache.nifi.processor.ProcessContext;
@@ -104,6 +105,7 @@ public class TestStandardProcessScheduler {
private ProcessGroup rootGroup;
private NiFiProperties nifiProperties;
private Bundle systemBundle;
+ private ExtensionDiscoveringManager extensionManager;
private volatile String propsFile = TestStandardProcessScheduler.class.getResource("/standardprocessschedulertest.nifi.properties").getFile();
@Before
@@ -115,7 +117,8 @@ public class TestStandardProcessScheduler {
// load the system bundle
systemBundle = SystemBundle.create(nifiProperties);
- ExtensionManager.discoverExtensions(systemBundle, Collections.emptySet());
+ extensionManager = new StandardExtensionDiscoveringManager();
+ extensionManager.discoverExtensions(systemBundle, Collections.emptySet());
scheduler = new StandardProcessScheduler(new FlowEngine(1, "Unit Test", true), Mockito.mock(FlowController.class), null, stateMgrProvider, nifiProperties);
scheduler.setSchedulingAgent(SchedulingStrategy.TIMER_DRIVEN, Mockito.mock(SchedulingAgent.class));
@@ -130,9 +133,10 @@ public class TestStandardProcessScheduler {
final ReloadComponent reloadComponent = Mockito.mock(ReloadComponent.class);
final LoggableComponent<ReportingTask> loggableComponent = new LoggableComponent<>(reportingTask, systemBundle.getBundleDetails().getCoordinate(), logger);
taskNode = new StandardReportingTaskNode(loggableComponent, UUID.randomUUID().toString(), null, scheduler, validationContextFactory,
- new StandardComponentVariableRegistry(variableRegistry), reloadComponent, new SynchronousValidationTrigger());
+ new StandardComponentVariableRegistry(variableRegistry), reloadComponent, extensionManager, new SynchronousValidationTrigger());
controller = Mockito.mock(FlowController.class);
+ Mockito.when(controller.getExtensionManager()).thenReturn(extensionManager);
final ConcurrentMap<String, ProcessorNode> processorMap = new ConcurrentHashMap<>();
Mockito.doAnswer(new Answer<ProcessorNode>() {
@@ -205,7 +209,8 @@ public class TestStandardProcessScheduler {
final LoggableComponent<Processor> loggableComponent = new LoggableComponent<>(proc, systemBundle.getBundleDetails().getCoordinate(), null);
final ProcessorNode procNode = new StandardProcessorNode(loggableComponent, uuid,
new StandardValidationContextFactory(serviceProvider, variableRegistry),
- scheduler, serviceProvider, nifiProperties, new StandardComponentVariableRegistry(VariableRegistry.EMPTY_REGISTRY), reloadComponent, new SynchronousValidationTrigger());
+ scheduler, serviceProvider, nifiProperties, new StandardComponentVariableRegistry(VariableRegistry.EMPTY_REGISTRY),
+ reloadComponent, extensionManager, new SynchronousValidationTrigger());
rootGroup.addProcessor(procNode);
Map<String, String> procProps = new HashMap<>();
@@ -507,7 +512,8 @@ public class TestStandardProcessScheduler {
final ProcessorNode procNode = new StandardProcessorNode(loggableComponent, UUID.randomUUID().toString(),
new StandardValidationContextFactory(controller, variableRegistry),
- scheduler, controller, nifiProperties, new StandardComponentVariableRegistry(VariableRegistry.EMPTY_REGISTRY), reloadComponent, new SynchronousValidationTrigger());
+ scheduler, controller, nifiProperties, new StandardComponentVariableRegistry(VariableRegistry.EMPTY_REGISTRY),
+ reloadComponent, extensionManager, new SynchronousValidationTrigger());
procNode.performValidation();
rootGroup.addProcessor(procNode);
@@ -533,7 +539,8 @@ public class TestStandardProcessScheduler {
final ProcessorNode procNode = new StandardProcessorNode(loggableComponent, UUID.randomUUID().toString(),
new StandardValidationContextFactory(controller, variableRegistry),
- scheduler, controller, nifiProperties, new StandardComponentVariableRegistry(VariableRegistry.EMPTY_REGISTRY), reloadComponent, new SynchronousValidationTrigger());
+ scheduler, controller, nifiProperties, new StandardComponentVariableRegistry(VariableRegistry.EMPTY_REGISTRY),
+ reloadComponent, extensionManager, new SynchronousValidationTrigger());
rootGroup.addProcessor(procNode);
@@ -562,7 +569,8 @@ public class TestStandardProcessScheduler {
final ProcessorNode procNode = new StandardProcessorNode(loggableComponent, UUID.randomUUID().toString(),
new StandardValidationContextFactory(controller, variableRegistry),
- scheduler, controller, nifiProperties, new StandardComponentVariableRegistry(VariableRegistry.EMPTY_REGISTRY), reloadComponent, new SynchronousValidationTrigger());
+ scheduler, controller, nifiProperties, new StandardComponentVariableRegistry(VariableRegistry.EMPTY_REGISTRY),
+ reloadComponent, extensionManager, new SynchronousValidationTrigger());
rootGroup.addProcessor(procNode);
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/serialization/StandardFlowSerializerTest.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/serialization/StandardFlowSerializerTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/serialization/StandardFlowSerializerTest.java
index 91a52a0..f019257 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/serialization/StandardFlowSerializerTest.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/serialization/StandardFlowSerializerTest.java
@@ -16,16 +16,6 @@
*/
package org.apache.nifi.controller.serialization;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.nio.charset.StandardCharsets;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.UUID;
import org.apache.commons.io.FileUtils;
import org.apache.nifi.admin.service.AuditService;
import org.apache.nifi.authorization.AbstractPolicyBasedAuthorizer;
@@ -36,7 +26,8 @@ import org.apache.nifi.controller.FlowController;
import org.apache.nifi.controller.ProcessorNode;
import org.apache.nifi.controller.repository.FlowFileEventRepository;
import org.apache.nifi.encrypt.StringEncryptor;
-import org.apache.nifi.nar.ExtensionManager;
+import org.apache.nifi.nar.ExtensionDiscoveringManager;
+import org.apache.nifi.nar.StandardExtensionDiscoveringManager;
import org.apache.nifi.nar.SystemBundle;
import org.apache.nifi.provenance.MockProvenanceRepository;
import org.apache.nifi.registry.VariableRegistry;
@@ -50,6 +41,17 @@ import org.junit.Test;
import org.mockito.Mockito;
import org.w3c.dom.Document;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
public class StandardFlowSerializerTest {
private static final String RAW_COMMENTS
@@ -60,6 +62,7 @@ public class StandardFlowSerializerTest {
private FlowController controller;
private Bundle systemBundle;
+ private ExtensionDiscoveringManager extensionManager;
private StandardFlowSerializer serializer;
@Before
@@ -78,14 +81,15 @@ public class StandardFlowSerializerTest {
// use the system bundle
systemBundle = SystemBundle.create(nifiProperties);
- ExtensionManager.discoverExtensions(systemBundle, Collections.emptySet());
+ extensionManager = new StandardExtensionDiscoveringManager();
+ extensionManager.discoverExtensions(systemBundle, Collections.emptySet());
final AbstractPolicyBasedAuthorizer authorizer = new MockPolicyBasedAuthorizer();
final VariableRegistry variableRegistry = new FileBasedVariableRegistry(nifiProperties.getVariableRegistryPropertiesPaths());
final BulletinRepository bulletinRepo = Mockito.mock(BulletinRepository.class);
controller = FlowController.createStandaloneInstance(flowFileEventRepo, nifiProperties, authorizer,
- auditService, encryptor, bulletinRepo, variableRegistry, Mockito.mock(FlowRegistryClient.class));
+ auditService, encryptor, bulletinRepo, variableRegistry, Mockito.mock(FlowRegistryClient.class), extensionManager);
serializer = new StandardFlowSerializer(encryptor);
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderIT.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderIT.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderIT.java
index e956944..0f4d3ce 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderIT.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderIT.java
@@ -17,16 +17,6 @@
package org.apache.nifi.controller.service;
-import static org.junit.Assert.assertTrue;
-
-import java.beans.PropertyDescriptor;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-
import org.apache.nifi.bundle.Bundle;
import org.apache.nifi.components.state.StateManager;
import org.apache.nifi.components.state.StateManagerProvider;
@@ -37,7 +27,8 @@ import org.apache.nifi.controller.service.mock.ServiceA;
import org.apache.nifi.controller.service.mock.ServiceB;
import org.apache.nifi.engine.FlowEngine;
import org.apache.nifi.groups.ProcessGroup;
-import org.apache.nifi.nar.ExtensionManager;
+import org.apache.nifi.nar.ExtensionDiscoveringManager;
+import org.apache.nifi.nar.StandardExtensionDiscoveringManager;
import org.apache.nifi.nar.SystemBundle;
import org.apache.nifi.registry.VariableRegistry;
import org.apache.nifi.util.NiFiProperties;
@@ -46,9 +37,20 @@ import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mockito;
+import java.beans.PropertyDescriptor;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+
+import static org.junit.Assert.assertTrue;
+
public class StandardControllerServiceProviderIT {
private static Bundle systemBundle;
private static NiFiProperties niFiProperties;
+ private static ExtensionDiscoveringManager extensionManager;
private static VariableRegistry variableRegistry = VariableRegistry.ENVIRONMENT_SYSTEM_REGISTRY;
private static StateManagerProvider stateManagerProvider = new StateManagerProvider() {
@@ -81,7 +83,8 @@ public class StandardControllerServiceProviderIT {
// load the system bundle
systemBundle = SystemBundle.create(niFiProperties);
- ExtensionManager.discoverExtensions(systemBundle, Collections.emptySet());
+ extensionManager = new StandardExtensionDiscoveringManager();
+ extensionManager.discoverExtensions(systemBundle, Collections.emptySet());
}
/**
@@ -102,6 +105,7 @@ public class StandardControllerServiceProviderIT {
final FlowController controller = Mockito.mock(FlowController.class);
final ProcessGroup procGroup = new MockProcessGroup(controller);
Mockito.when(controller.getGroup(Mockito.anyString())).thenReturn(procGroup);
+ Mockito.when(controller.getExtensionManager()).thenReturn(extensionManager);
final StandardControllerServiceProvider provider = new StandardControllerServiceProvider(controller, scheduler, null,
stateManagerProvider, variableRegistry, niFiProperties, new SynchronousValidationTrigger());
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderTest.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderTest.java
index f7ee72f..0a0b05f 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderTest.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/StandardControllerServiceProviderTest.java
@@ -20,8 +20,9 @@ import org.apache.nifi.bundle.Bundle;
import org.apache.nifi.components.state.StateManager;
import org.apache.nifi.components.state.StateManagerProvider;
import org.apache.nifi.controller.ControllerService;
-import org.apache.nifi.nar.ExtensionManager;
-import org.apache.nifi.nar.NarClassLoaders;
+import org.apache.nifi.controller.FlowController;
+import org.apache.nifi.nar.ExtensionDiscoveringManager;
+import org.apache.nifi.nar.StandardExtensionDiscoveringManager;
import org.apache.nifi.nar.SystemBundle;
import org.apache.nifi.registry.VariableRegistry;
import org.apache.nifi.registry.variable.FileBasedVariableRegistry;
@@ -33,6 +34,8 @@ import org.junit.BeforeClass;
import org.junit.Test;
import org.mockito.Mockito;
+import java.util.Collections;
+
public class StandardControllerServiceProviderTest {
@@ -40,27 +43,31 @@ public class StandardControllerServiceProviderTest {
private ControllerService implementation;
private static VariableRegistry variableRegistry;
private static NiFiProperties nifiProperties;
+ private static ExtensionDiscoveringManager extensionManager;
private static Bundle systemBundle;
+ private static FlowController flowController;
@BeforeClass
public static void setupSuite() throws Exception {
System.setProperty(NiFiProperties.PROPERTIES_FILE_PATH, StandardControllerServiceProviderTest.class.getResource("/conf/nifi.properties").getFile());
nifiProperties = NiFiProperties.createBasicNiFiProperties(null, null);
- NarClassLoaders.getInstance().init(nifiProperties.getFrameworkWorkingDirectory(), nifiProperties.getExtensionsWorkingDirectory());
-
// load the system bundle
systemBundle = SystemBundle.create(nifiProperties);
- ExtensionManager.discoverExtensions(systemBundle, NarClassLoaders.getInstance().getBundles());
+ extensionManager = new StandardExtensionDiscoveringManager();
+ extensionManager.discoverExtensions(systemBundle, Collections.emptySet());
variableRegistry = new FileBasedVariableRegistry(nifiProperties.getVariableRegistryPropertiesPaths());
+
+ flowController = Mockito.mock(FlowController.class);
+ Mockito.when(flowController.getExtensionManager()).thenReturn(extensionManager);
}
@Before
public void setup() throws Exception {
String id = "id";
String clazz = "org.apache.nifi.controller.service.util.TestControllerService";
- ControllerServiceProvider provider = new StandardControllerServiceProvider(null, null, null, new StateManagerProvider() {
+ ControllerServiceProvider provider = new StandardControllerServiceProvider(flowController, null, null, new StateManagerProvider() {
@Override
public StateManager getStateManager(final String componentId) {
return Mockito.mock(StateManager.class);
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/TestStandardControllerServiceProvider.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/TestStandardControllerServiceProvider.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/TestStandardControllerServiceProvider.java
index b37dbb2..d317000 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/TestStandardControllerServiceProvider.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/controller/service/TestStandardControllerServiceProvider.java
@@ -17,20 +17,6 @@
*/
package org.apache.nifi.controller.service;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-import java.util.concurrent.TimeUnit;
-
import org.apache.nifi.bundle.Bundle;
import org.apache.nifi.components.state.StateManager;
import org.apache.nifi.components.state.StateManagerProvider;
@@ -49,7 +35,8 @@ import org.apache.nifi.controller.service.mock.ServiceC;
import org.apache.nifi.engine.FlowEngine;
import org.apache.nifi.groups.ProcessGroup;
import org.apache.nifi.groups.StandardProcessGroup;
-import org.apache.nifi.nar.ExtensionManager;
+import org.apache.nifi.nar.ExtensionDiscoveringManager;
+import org.apache.nifi.nar.StandardExtensionDiscoveringManager;
import org.apache.nifi.nar.SystemBundle;
import org.apache.nifi.processor.Processor;
import org.apache.nifi.processor.StandardValidationContextFactory;
@@ -68,6 +55,20 @@ import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.TimeUnit;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
public class TestStandardControllerServiceProvider {
private static StateManagerProvider stateManagerProvider = new StateManagerProvider() {
@@ -95,6 +96,7 @@ public class TestStandardControllerServiceProvider {
private static VariableRegistry variableRegistry = VariableRegistry.ENVIRONMENT_SYSTEM_REGISTRY;
private static NiFiProperties niFiProperties;
+ private static ExtensionDiscoveringManager extensionManager;
private static Bundle systemBundle;
private FlowController controller;
@@ -105,12 +107,14 @@ public class TestStandardControllerServiceProvider {
// load the system bundle
systemBundle = SystemBundle.create(niFiProperties);
- ExtensionManager.discoverExtensions(systemBundle, Collections.emptySet());
+ extensionManager = new StandardExtensionDiscoveringManager();
+ extensionManager.discoverExtensions(systemBundle, Collections.emptySet());
}
@Before
public void setup() {
controller = Mockito.mock(FlowController.class);
+ Mockito.when(controller.getExtensionManager()).thenReturn(extensionManager);
final ConcurrentMap<String, ProcessorNode> processorMap = new ConcurrentHashMap<>();
Mockito.doAnswer(new Answer<ProcessorNode>() {
@@ -146,6 +150,7 @@ public class TestStandardControllerServiceProvider {
final ProcessGroup procGroup = new MockProcessGroup(controller);
final FlowController controller = Mockito.mock(FlowController.class);
Mockito.when(controller.getGroup(Mockito.anyString())).thenReturn(procGroup);
+ Mockito.when(controller.getExtensionManager()).thenReturn(extensionManager);
final StandardProcessScheduler scheduler = createScheduler();
final StandardControllerServiceProvider provider =
@@ -164,6 +169,7 @@ public class TestStandardControllerServiceProvider {
final ProcessGroup group = new MockProcessGroup(controller);
final FlowController controller = Mockito.mock(FlowController.class);
Mockito.when(controller.getGroup(Mockito.anyString())).thenReturn(group);
+ Mockito.when(controller.getExtensionManager()).thenReturn(extensionManager);
final StandardProcessScheduler scheduler = createScheduler();
final StandardControllerServiceProvider provider =
@@ -219,6 +225,7 @@ public class TestStandardControllerServiceProvider {
final ProcessGroup procGroup = new MockProcessGroup(controller);
final FlowController controller = Mockito.mock(FlowController.class);
Mockito.when(controller.getGroup(Mockito.anyString())).thenReturn(procGroup);
+ Mockito.when(controller.getExtensionManager()).thenReturn(extensionManager);
final StandardControllerServiceProvider provider =
new StandardControllerServiceProvider(controller, null, null, stateManagerProvider, variableRegistry, niFiProperties, new SynchronousValidationTrigger());
@@ -379,7 +386,7 @@ public class TestStandardControllerServiceProvider {
final LoggableComponent<Processor> dummyProcessor = new LoggableComponent<>(processor, systemBundle.getBundleDetails().getCoordinate(), null);
final ProcessorNode procNode = new StandardProcessorNode(dummyProcessor, mockInitContext.getIdentifier(),
new StandardValidationContextFactory(serviceProvider, null), scheduler, serviceProvider, niFiProperties,
- new StandardComponentVariableRegistry(VariableRegistry.EMPTY_REGISTRY), reloadComponent, new SynchronousValidationTrigger());
+ new StandardComponentVariableRegistry(VariableRegistry.EMPTY_REGISTRY), reloadComponent, extensionManager, new SynchronousValidationTrigger());
final ProcessGroup group = new StandardProcessGroup(UUID.randomUUID().toString(), serviceProvider, scheduler, null, null, Mockito.mock(FlowController.class),
new MutableVariableRegistry(variableRegistry));
@@ -394,6 +401,7 @@ public class TestStandardControllerServiceProvider {
final ProcessGroup procGroup = new MockProcessGroup(controller);
final FlowController controller = Mockito.mock(FlowController.class);
Mockito.when(controller.getGroup(Mockito.anyString())).thenReturn(procGroup);
+ Mockito.when(controller.getExtensionManager()).thenReturn(extensionManager);
final StandardProcessScheduler scheduler = createScheduler();
final StandardControllerServiceProvider provider =
@@ -421,6 +429,7 @@ public class TestStandardControllerServiceProvider {
new StandardControllerServiceProvider(controller, scheduler, null, stateManagerProvider, variableRegistry, niFiProperties, new SynchronousValidationTrigger());
ProcessGroup procGroup = new MockProcessGroup(controller);
Mockito.when(controller.getGroup(Mockito.anyString())).thenReturn(procGroup);
+ Mockito.when(controller.getExtensionManager()).thenReturn(extensionManager);
ControllerServiceNode A = provider.createControllerService(ServiceA.class.getName(), "A",
systemBundle.getBundleDetails().getCoordinate(), null, false);
@@ -474,6 +483,7 @@ public class TestStandardControllerServiceProvider {
stateManagerProvider, variableRegistry, niFiProperties, new SynchronousValidationTrigger());
ProcessGroup procGroup = new MockProcessGroup(controller);
Mockito.when(controller.getGroup(Mockito.anyString())).thenReturn(procGroup);
+ Mockito.when(controller.getExtensionManager()).thenReturn(extensionManager);
ControllerServiceNode A = provider.createControllerService(ServiceC.class.getName(), "A",
systemBundle.getBundleDetails().getCoordinate(), null, false);
@@ -519,6 +529,7 @@ public class TestStandardControllerServiceProvider {
new StandardControllerServiceProvider(controller, scheduler, null, stateManagerProvider, variableRegistry, niFiProperties, new SynchronousValidationTrigger());
ProcessGroup procGroup = new MockProcessGroup(controller);
Mockito.when(controller.getGroup(Mockito.anyString())).thenReturn(procGroup);
+ Mockito.when(controller.getExtensionManager()).thenReturn(extensionManager);
ControllerServiceNode serviceNode1 = provider.createControllerService(ServiceA.class.getName(), "1",
systemBundle.getBundleDetails().getCoordinate(), null, false);
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/fingerprint/FingerprintFactoryTest.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/fingerprint/FingerprintFactoryTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/fingerprint/FingerprintFactoryTest.java
index 30294a4..09acbc9 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/fingerprint/FingerprintFactoryTest.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-core/src/test/java/org/apache/nifi/fingerprint/FingerprintFactoryTest.java
@@ -43,6 +43,8 @@ import org.apache.nifi.controller.serialization.ScheduledStateLookup;
import org.apache.nifi.controller.serialization.StandardFlowSerializer;
import org.apache.nifi.encrypt.StringEncryptor;
import org.apache.nifi.groups.RemoteProcessGroup;
+import org.apache.nifi.nar.ExtensionManager;
+import org.apache.nifi.nar.StandardExtensionDiscoveringManager;
import org.apache.nifi.remote.RemoteGroupPort;
import org.apache.nifi.remote.protocol.SiteToSiteTransportProtocol;
import org.junit.Before;
@@ -58,12 +60,14 @@ import org.xml.sax.SAXParseException;
public class FingerprintFactoryTest {
private StringEncryptor encryptor;
+ private ExtensionManager extensionManager;
private FingerprintFactory fingerprinter;
@Before
public void setup() {
encryptor = new StringEncryptor("PBEWITHMD5AND256BITAES-CBC-OPENSSL", "BC", "nififtw!");
- fingerprinter = new FingerprintFactory(encryptor);
+ extensionManager = new StandardExtensionDiscoveringManager();
+ fingerprinter = new FingerprintFactory(encryptor, extensionManager);
}
@Test
@@ -122,7 +126,7 @@ public class FingerprintFactoryTest {
@Test
public void testSchemaValidation() throws IOException {
- FingerprintFactory fp = new FingerprintFactory(null, getValidatingDocumentBuilder());
+ FingerprintFactory fp = new FingerprintFactory(null, getValidatingDocumentBuilder(), extensionManager);
final String fingerprint = fp.createFingerprint(getResourceBytes("/nifi/fingerprint/validating-flow.xml"), null);
}
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/pom.xml
new file mode 100644
index 0000000..1d4e2de
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/pom.xml
@@ -0,0 +1,46 @@
+<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-framework</artifactId>
+ <version>1.9.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>nifi-framework-nar-loading-utils</artifactId>
+ <packaging>jar</packaging>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.nifi</groupId>
+ <artifactId>nifi-nar-utils</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.nifi</groupId>
+ <artifactId>nifi-documentation</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.nifi</groupId>
+ <artifactId>nifi-properties</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.nifi</groupId>
+ <artifactId>nifi-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.nifi</groupId>
+ <artifactId>nifi-framework-api</artifactId>
+ </dependency>
+ </dependencies>
+</project>
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/main/java/org/apache/nifi/nar/ExtensionUiLoader.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/main/java/org/apache/nifi/nar/ExtensionUiLoader.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/main/java/org/apache/nifi/nar/ExtensionUiLoader.java
new file mode 100644
index 0000000..0c5b02b
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/main/java/org/apache/nifi/nar/ExtensionUiLoader.java
@@ -0,0 +1,33 @@
+/*
+ * 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.nar;
+
+import org.apache.nifi.bundle.Bundle;
+
+import java.util.Set;
+
+/**
+ * Loads WARs from extensions and makes them available to the running application.
+ */
+public interface ExtensionUiLoader {
+
+ /**
+ * @param bundles the set of bundles to load WARs from
+ */
+ void loadExtensionUis(Set<Bundle> bundles);
+
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/main/java/org/apache/nifi/nar/NarAutoLoader.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/main/java/org/apache/nifi/nar/NarAutoLoader.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/main/java/org/apache/nifi/nar/NarAutoLoader.java
new file mode 100644
index 0000000..2ac55a0
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/main/java/org/apache/nifi/nar/NarAutoLoader.java
@@ -0,0 +1,87 @@
+/*
+ * 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.nar;
+
+import org.apache.nifi.util.FileUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.nio.file.StandardWatchEventKinds;
+import java.nio.file.WatchService;
+import java.util.Objects;
+
+/**
+ * Starts a thread to monitor the auto-load directory for new NARs.
+ */
+public class NarAutoLoader {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(NarAutoLoader.class);
+
+ private static final long POLL_INTERVAL_MS = 5000;
+
+ private final File autoLoadDir;
+ private final NarLoader narLoader;
+
+ private volatile NarAutoLoaderTask narAutoLoaderTask;
+ private volatile boolean started = false;
+
+ public NarAutoLoader(final File autoLoadDir, final NarLoader narLoader) {
+ this.autoLoadDir = Objects.requireNonNull(autoLoadDir);
+ this.narLoader = Objects.requireNonNull(narLoader);
+ }
+
+ public synchronized void start() throws IOException {
+ if (started) {
+ return;
+ }
+
+ FileUtils.ensureDirectoryExistAndCanReadAndWrite(autoLoadDir);
+
+ final WatchService watcher = FileSystems.getDefault().newWatchService();
+
+ final Path autoLoadPath = autoLoadDir.toPath();
+ autoLoadPath.register(watcher, StandardWatchEventKinds.ENTRY_CREATE);
+
+ narAutoLoaderTask = new NarAutoLoaderTask.Builder()
+ .autoLoadPath(autoLoadPath)
+ .watchService(watcher)
+ .pollIntervalMillis(POLL_INTERVAL_MS)
+ .narLoader(narLoader)
+ .build();
+
+ LOGGER.info("Starting NAR Auto-Loader for directory {} ...", new Object[]{autoLoadPath});
+
+ final Thread thread = new Thread(narAutoLoaderTask);
+ thread.setName("NAR Auto-Loader");
+ thread.setDaemon(true);
+ thread.start();
+
+ LOGGER.info("NAR Auto-Loader started");
+ started = true;
+ }
+
+ public synchronized void stop() {
+ started = false;
+ narAutoLoaderTask.stop();
+ LOGGER.info("NAR Auto-Loader stopped");
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/main/java/org/apache/nifi/nar/NarAutoLoaderTask.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/main/java/org/apache/nifi/nar/NarAutoLoaderTask.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/main/java/org/apache/nifi/nar/NarAutoLoaderTask.java
new file mode 100644
index 0000000..260fe10
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/main/java/org/apache/nifi/nar/NarAutoLoaderTask.java
@@ -0,0 +1,178 @@
+/*
+ * 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.nar;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.StandardWatchEventKinds;
+import java.nio.file.WatchEvent;
+import java.nio.file.WatchKey;
+import java.nio.file.WatchService;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * The runnable task that polls the WatchService for new NAR files found in the auto-load directory.
+ *
+ * Each new NAR file found will be passed to the NarLoader to be unpacked and loaded into the ExtensionManager.
+ *
+ */
+public class NarAutoLoaderTask implements Runnable {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(NarAutoLoaderTask.class);
+
+ private static final long MIN_FILE_AGE = 5000;
+
+ private final Path autoLoadPath;
+ private final WatchService watchService;
+ private final long pollIntervalMillis;
+ private final NarLoader narLoader;
+ private final List<File> candidateNars;
+
+ private volatile boolean stopped = false;
+
+ private NarAutoLoaderTask(final Builder builder) {
+ this.autoLoadPath = builder.autoLoadPath;
+ this.watchService = builder.watchService;
+ this.pollIntervalMillis = builder.pollIntervalMillis;
+ this.narLoader = builder.narLoader;
+ this.candidateNars = new ArrayList<>();
+ }
+
+ @Override
+ public void run() {
+ while (!stopped) {
+ try {
+ WatchKey key;
+ try {
+ LOGGER.debug("Polling for new NARs at {}", new Object[]{autoLoadPath});
+ key = watchService.poll(pollIntervalMillis, TimeUnit.MILLISECONDS);
+ } catch (InterruptedException x) {
+ LOGGER.info("WatchService interrupted, returning...");
+ return;
+ }
+
+ // Key comes back as null when there are no new create events, but we still want to continue processing
+ // so we can consider files added to the candidateNars list in previous iterations
+
+ if (key != null) {
+ for (WatchEvent<?> event : key.pollEvents()) {
+ final WatchEvent.Kind<?> kind = event.kind();
+ if (kind == StandardWatchEventKinds.OVERFLOW) {
+ continue;
+ }
+
+ final WatchEvent<Path> ev = (WatchEvent<Path>) event;
+ final Path filename = ev.context();
+
+ final Path autoLoadFile = autoLoadPath.resolve(filename);
+ final String autoLoadFilename = autoLoadFile.toFile().getName().toLowerCase();
+
+ if (!autoLoadFilename.endsWith(".nar")) {
+ LOGGER.info("Skipping non-nar file {}", new Object[]{autoLoadFilename});
+ continue;
+ }
+
+ if (autoLoadFilename.startsWith(".")) {
+ LOGGER.debug("Skipping partially written file {}", new Object[]{autoLoadFilename});
+ continue;
+ }
+
+ LOGGER.info("Found {} in auto-load directory", new Object[]{autoLoadFile});
+ candidateNars.add(autoLoadFile.toFile());
+ }
+
+ final boolean valid = key.reset();
+ if (!valid) {
+ LOGGER.error("NAR auto-load directory is no longer valid");
+ stop();
+ }
+ }
+
+ // Make sure that the created file is done being written by checking the last modified date of the file and
+ // make sure a certain amount of time has passed indicating it is done being written to
+
+ final List<File> readyNars = new ArrayList<>();
+ final Iterator<File> candidateNarIter = candidateNars.iterator();
+ while (candidateNarIter.hasNext()) {
+ final File candidateNar = candidateNarIter.next();
+ final long fileAge = System.currentTimeMillis() - candidateNar.lastModified();
+ if (fileAge >= MIN_FILE_AGE) {
+ readyNars.add(candidateNar);
+ candidateNarIter.remove();
+ } else {
+ LOGGER.debug("Candidate NAR {} not ready yet, will check again next time", new Object[]{candidateNar.getName()});
+ }
+ }
+
+ if (!readyNars.isEmpty()) {
+ narLoader.load(readyNars);
+ }
+
+ } catch (final Exception e) {
+ LOGGER.error("Error loading NARs due to: " + e.getMessage(), e);
+ }
+ }
+ }
+
+ public void stop() {
+ LOGGER.info("Stopping NAR Auto-loader");
+ stopped = true;
+ }
+
+ /**
+ * Builder for NarAutoLoaderTask.
+ */
+ public static class Builder {
+
+ private Path autoLoadPath;
+ private WatchService watchService;
+ private long pollIntervalMillis;
+ private NarLoader narLoader;
+
+ public Builder autoLoadPath(final Path autoLoadPath) {
+ this.autoLoadPath = autoLoadPath;
+ return this;
+ }
+
+ public Builder watchService(final WatchService watchService) {
+ this.watchService = watchService;
+ return this;
+ }
+
+ public Builder pollIntervalMillis(final long pollIntervalMillis) {
+ this.pollIntervalMillis = pollIntervalMillis;
+ return this;
+ }
+
+ public Builder narLoader(final NarLoader narLoader) {
+ this.narLoader = narLoader;
+ return this;
+ }
+
+ public NarAutoLoaderTask build() {
+ return new NarAutoLoaderTask(this);
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/main/java/org/apache/nifi/nar/NarLoader.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/main/java/org/apache/nifi/nar/NarLoader.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/main/java/org/apache/nifi/nar/NarLoader.java
new file mode 100644
index 0000000..6aa4d43
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/main/java/org/apache/nifi/nar/NarLoader.java
@@ -0,0 +1,35 @@
+/*
+ * 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.nar;
+
+import java.io.File;
+import java.util.Collection;
+
+/**
+ * Responsible for loading NARs into the running application.
+ */
+public interface NarLoader {
+
+ /**
+ * Loads the given NARs.
+ *
+ * @param narFiles the collection of NAR files to load
+ * @return the result of loading the NARs (i.e. bundles that were loaded, bundles that were skipped)
+ */
+ NarLoadResult load(final Collection<File> narFiles);
+
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/main/java/org/apache/nifi/nar/StandardNarLoader.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/main/java/org/apache/nifi/nar/StandardNarLoader.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/main/java/org/apache/nifi/nar/StandardNarLoader.java
new file mode 100644
index 0000000..2ddca01
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/main/java/org/apache/nifi/nar/StandardNarLoader.java
@@ -0,0 +1,167 @@
+/*
+ * 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.nar;
+
+import org.apache.nifi.bundle.Bundle;
+import org.apache.nifi.bundle.BundleCoordinate;
+import org.apache.nifi.bundle.BundleDetails;
+import org.apache.nifi.documentation.DocGenerator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.jar.Attributes;
+import java.util.jar.JarFile;
+import java.util.jar.Manifest;
+
+/**
+ * Loads a set of NARs from the file system into the running application.
+ *
+ * NOTE: Initially this will only be used from the NarAutoLoader which is watching a directory for new files, but eventually
+ * this may also be used for loading a NAR that was downloaded from the extension registry, and thus the load method
+ * is synchronized to ensure only one set of NARs can be in process of loading at a given time.
+ */
+public class StandardNarLoader implements NarLoader {
+
+ private static Logger LOGGER = LoggerFactory.getLogger(StandardNarLoader.class);
+
+ private final File extensionsWorkingDir;
+ private final File docsWorkingDir;
+ private final NarClassLoaders narClassLoaders;
+ private final ExtensionDiscoveringManager extensionManager;
+ private final ExtensionMapping extensionMapping;
+ private final ExtensionUiLoader extensionUiLoader;
+
+ private Set<BundleDetails> previouslySkippedBundles;
+
+ public StandardNarLoader(final File extensionsWorkingDir,
+ final File docsWorkingDir,
+ final NarClassLoaders narClassLoaders,
+ final ExtensionDiscoveringManager extensionManager,
+ final ExtensionMapping extensionMapping,
+ final ExtensionUiLoader extensionUiLoader) {
+ this.extensionsWorkingDir = extensionsWorkingDir;
+ this.docsWorkingDir = docsWorkingDir;
+ this.narClassLoaders = narClassLoaders;
+ this.extensionManager = extensionManager;
+ this.extensionMapping = extensionMapping;
+ this.extensionUiLoader = extensionUiLoader;
+ }
+
+ @Override
+ public synchronized NarLoadResult load(final Collection<File> narFiles) {
+ LOGGER.info("Starting load process for {} NARs...", new Object[]{narFiles.size()});
+
+ final List<File> unpackedNars = new ArrayList<>();
+
+ for (final File narFile : narFiles) {
+ LOGGER.debug("Unpacking {}...", new Object[]{narFile.getName()});
+ final File unpackedNar = unpack(narFile);
+ if (unpackedNar != null) {
+ LOGGER.debug("Completed unpacking {}", new Object[]{narFile.getName()});
+ unpackedNars.add(unpackedNar);
+ }
+ }
+
+ if (previouslySkippedBundles != null && !previouslySkippedBundles.isEmpty()) {
+ LOGGER.info("Including {} previously skipped bundle(s)", new Object[]{previouslySkippedBundles.size()});
+ previouslySkippedBundles.forEach(b -> unpackedNars.add(b.getWorkingDirectory()));
+ }
+
+ if (unpackedNars.isEmpty()) {
+ LOGGER.info("No NARs were unpacked, nothing to do");
+ return new NarLoadResult(Collections.emptySet(), Collections.emptySet());
+ }
+
+ LOGGER.info("Creating class loaders for {} NARs...", new Object[]{unpackedNars.size()});
+
+ final NarLoadResult narLoadResult = narClassLoaders.loadAdditionalNars(unpackedNars);
+ final Set<Bundle> loadedBundles = narLoadResult.getLoadedBundles();
+ final Set<BundleDetails> skippedBundles = narLoadResult.getSkippedBundles();
+
+ LOGGER.info("Successfully created class loaders for {} NARs, {} were skipped",
+ new Object[]{loadedBundles.size(), skippedBundles.size()});
+
+ // Store skipped bundles for next iteration
+ previouslySkippedBundles = new HashSet<>(skippedBundles);
+
+ if (!loadedBundles.isEmpty()) {
+ LOGGER.debug("Discovering extensions...");
+ extensionManager.discoverExtensions(loadedBundles);
+
+ // Call the DocGenerator for the classes that were loaded from each Bundle
+ for (final Bundle bundle : loadedBundles) {
+ final BundleCoordinate bundleCoordinate = bundle.getBundleDetails().getCoordinate();
+ final Set<Class> extensions = extensionManager.getTypes(bundleCoordinate);
+ if (extensions.isEmpty()) {
+ LOGGER.debug("No documentation to generate for {} because no extensions were found",
+ new Object[]{bundleCoordinate.getCoordinate()});
+ } else {
+ LOGGER.debug("Generating documentation for {} extensions in {}",
+ new Object[]{extensions.size(), bundleCoordinate.getCoordinate()});
+ DocGenerator.documentConfigurableComponent(extensions, docsWorkingDir, extensionManager);
+ }
+ }
+
+ LOGGER.debug("Loading custom UIs for extensions...");
+ extensionUiLoader.loadExtensionUis(loadedBundles);
+ }
+
+ LOGGER.info("Finished NAR loading process!");
+ return narLoadResult;
+ }
+
+ private File unpack(final File narFile) {
+ try (final JarFile nar = new JarFile(narFile)) {
+ final Manifest manifest = nar.getManifest();
+
+ final Attributes attributes = manifest.getMainAttributes();
+ final String groupId = attributes.getValue(NarManifestEntry.NAR_GROUP.getManifestName());
+ final String narId = attributes.getValue(NarManifestEntry.NAR_ID.getManifestName());
+ final String version = attributes.getValue(NarManifestEntry.NAR_VERSION.getManifestName());
+
+ if (NarClassLoaders.FRAMEWORK_NAR_ID.equals(narId)) {
+ LOGGER.error("Found a framework NAR, will not load {}", new Object[]{narFile.getAbsolutePath()});
+ return null;
+ }
+
+ final BundleCoordinate coordinate = new BundleCoordinate(groupId, narId, version);
+
+ final Bundle bundle = extensionManager.getBundle(coordinate);
+ if (bundle != null) {
+ LOGGER.warn("Found existing bundle with coordinate {}, will not load {}",
+ new Object[]{coordinate, narFile.getAbsolutePath()});
+ return null;
+ }
+
+ final File unpackedExtension = NarUnpacker.unpackNar(narFile, extensionsWorkingDir);
+ NarUnpacker.mapExtension(unpackedExtension, coordinate, docsWorkingDir, extensionMapping);
+ return unpackedExtension;
+
+ } catch (Exception e) {
+ LOGGER.error("Error unpacking " + narFile.getAbsolutePath(), e);
+ return null;
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/java/org/apache/nifi/nar/TestNarLoader.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/java/org/apache/nifi/nar/TestNarLoader.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/java/org/apache/nifi/nar/TestNarLoader.java
new file mode 100644
index 0000000..66cb829
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/java/org/apache/nifi/nar/TestNarLoader.java
@@ -0,0 +1,189 @@
+/*
+ * 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.nar;
+
+import org.apache.nifi.bundle.Bundle;
+import org.apache.nifi.controller.ControllerService;
+import org.apache.nifi.processor.Processor;
+import org.apache.nifi.reporting.ReportingTask;
+import org.apache.nifi.util.NiFiProperties;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.StandardCopyOption;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+
+public class TestNarLoader {
+
+ static final String WORK_DIR = "./target/work";
+ static final String NAR_AUTOLOAD_DIR = "./target/extensions";
+ static final String EXTENSIONS_DIR = "./src/test/resources/extensions";
+
+ private NiFiProperties properties;
+ private ExtensionMapping extensionMapping;
+
+ private StandardNarLoader narLoader;
+ private NarClassLoaders narClassLoaders;
+ private ExtensionDiscoveringManager extensionManager;
+
+ @Before
+ public void setup() throws IOException, ClassNotFoundException {
+ deleteDir(WORK_DIR);
+ deleteDir(NAR_AUTOLOAD_DIR);
+
+ final File extensionsDir = new File(NAR_AUTOLOAD_DIR);
+ assertTrue(extensionsDir.mkdirs());
+
+ // Create NiFiProperties
+ final String propertiesFile = "./src/test/resources/conf/nifi.properties";
+ properties = NiFiProperties.createBasicNiFiProperties(propertiesFile , Collections.emptyMap());
+
+ // Unpack NARs
+ final Bundle systemBundle = SystemBundle.create(properties);
+ extensionMapping = NarUnpacker.unpackNars(properties, systemBundle);
+ assertEquals(0, extensionMapping.getAllExtensionNames().size());
+
+ // Initialize NarClassLoaders
+ narClassLoaders = new NarClassLoaders();
+ narClassLoaders.init(properties.getFrameworkWorkingDirectory(), properties.getExtensionsWorkingDirectory());
+
+ extensionManager = new StandardExtensionDiscoveringManager();
+ extensionManager.discoverExtensions(systemBundle, narClassLoaders.getBundles());
+
+ // Should have Framework and Jetty NARs loaded here
+ assertEquals(2, narClassLoaders.getBundles().size());
+
+ // No extensions should be loaded yet
+ assertEquals(0, extensionManager.getExtensions(Processor.class).size());
+ assertEquals(0, extensionManager.getExtensions(ControllerService.class).size());
+ assertEquals(0, extensionManager.getExtensions(ReportingTask.class).size());
+
+ // Create class we are testing
+ narLoader = new StandardNarLoader(
+ properties.getExtensionsWorkingDirectory(),
+ properties.getComponentDocumentationWorkingDirectory(),
+ narClassLoaders,
+ extensionManager,
+ extensionMapping,
+ (bundles) -> {});
+ }
+
+ @Test
+ public void testNarLoaderWhenAllAvailable() throws IOException {
+ // Copy all NARs from src/test/resources/extensions to target/extensions
+ final File extensionsDir = new File(EXTENSIONS_DIR);
+ final Path narAutoLoadDir = Paths.get(NAR_AUTOLOAD_DIR);
+ for (final File extensionFile : extensionsDir.listFiles()) {
+ Files.copy(extensionFile.toPath(), narAutoLoadDir.resolve(extensionFile.getName()), StandardCopyOption.REPLACE_EXISTING);
+ }
+
+ final List<File> narFiles = Arrays.asList(narAutoLoadDir.toFile().listFiles());
+ assertEquals(3, narFiles.size());
+
+ final NarLoadResult narLoadResult = narLoader.load(narFiles);
+ assertNotNull(narLoadResult);
+ assertEquals(3, narLoadResult.getLoadedBundles().size());
+ assertEquals(0, narLoadResult.getSkippedBundles().size());
+
+ assertEquals(5, narClassLoaders.getBundles().size());
+ assertEquals(1, extensionManager.getExtensions(Processor.class).size());
+ assertEquals(1, extensionManager.getExtensions(ControllerService.class).size());
+ assertEquals(0, extensionManager.getExtensions(ReportingTask.class).size());
+ }
+
+ @Test
+ public void testNarLoaderWhenDependentNarsAreMissing() throws IOException {
+ final File extensionsDir = new File(EXTENSIONS_DIR);
+ final Path narAutoLoadDir = Paths.get(NAR_AUTOLOAD_DIR);
+
+ // Copy processors NAR first which depends on service API NAR
+ final File processorsNar = new File(extensionsDir, "nifi-example-processors-nar-1.0.nar");
+ final File targetProcessorNar = new File(narAutoLoadDir.toFile(), processorsNar.getName());
+ Files.copy(processorsNar.toPath(), targetProcessorNar.toPath(), StandardCopyOption.REPLACE_EXISTING);
+
+ // Attempt to load while only processor NAR is available
+ final List<File> narFiles1 = Arrays.asList(targetProcessorNar);
+ final NarLoadResult narLoadResult1 = narLoader.load(narFiles1);
+ assertNotNull(narLoadResult1);
+ assertEquals(0, narLoadResult1.getLoadedBundles().size());
+ assertEquals(1, narLoadResult1.getSkippedBundles().size());
+
+ // Copy the service impl which also depends on service API NAR
+ final File serviceImplNar = new File(extensionsDir, "nifi-example-service-nar-1.1.nar");
+ final File targetServiceImplNar = new File(narAutoLoadDir.toFile(), serviceImplNar.getName());
+ Files.copy(serviceImplNar.toPath(), targetServiceImplNar.toPath(), StandardCopyOption.REPLACE_EXISTING);
+
+ // Attempt to load while processor and service impl NARs available
+ final List<File> narFiles2 = Arrays.asList(targetServiceImplNar);
+ final NarLoadResult narLoadResult2 = narLoader.load(narFiles2);
+ assertNotNull(narLoadResult2);
+ assertEquals(0, narLoadResult2.getLoadedBundles().size());
+ assertEquals(2, narLoadResult2.getSkippedBundles().size());
+
+ // Copy service API NAR
+ final File serviceApiNar = new File(extensionsDir, "nifi-example-service-api-nar-1.0.nar");
+ final File targetServiceApiNar = new File(narAutoLoadDir.toFile(), serviceApiNar.getName());
+ Files.copy(serviceApiNar.toPath(), targetServiceApiNar.toPath(), StandardCopyOption.REPLACE_EXISTING);
+
+ // Attempt to load while all NARs available
+ final List<File> narFiles3 = Arrays.asList(targetServiceApiNar);
+ final NarLoadResult narLoadResult3 = narLoader.load(narFiles3);
+ assertNotNull(narLoadResult3);
+ assertEquals(3, narLoadResult3.getLoadedBundles().size());
+ assertEquals(0, narLoadResult3.getSkippedBundles().size());
+
+ assertEquals(5, narClassLoaders.getBundles().size());
+ assertEquals(1, extensionManager.getExtensions(Processor.class).size());
+ assertEquals(1, extensionManager.getExtensions(ControllerService.class).size());
+ assertEquals(0, extensionManager.getExtensions(ReportingTask.class).size());
+ }
+
+ private void deleteDir(String path) throws IOException {
+ Path directory = Paths.get(path);
+ if (!directory.toFile().exists()) {
+ return;
+ }
+
+ Files.walkFileTree(directory, new SimpleFileVisitor<Path>() {
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
+ Files.delete(file);
+ return FileVisitResult.CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
+ Files.delete(dir);
+ return FileVisitResult.CONTINUE;
+ }
+ });
+ }
+}
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/README
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/README b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/README
new file mode 100644
index 0000000..1782c2f
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/README
@@ -0,0 +1,9 @@
+The NARs in src/test/resources/extensions came from building the source code found in nifi-example-nars-source.zip.
+
+If you need to make a change to these NARs, perform the following steps:
+
+1) Copy nifi-example-nars-source.zip somewhere and extract it
+2) Modify code and build
+3) Replace NARs in src/test/resources/extensions with results from build in step 2
+4) Create a zip archive of the modified source code
+5) Replace nifi-example-nars-source.zip with the new zip archive
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/conf/nifi.properties
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/conf/nifi.properties b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/conf/nifi.properties
new file mode 100644
index 0000000..987a550
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/conf/nifi.properties
@@ -0,0 +1,124 @@
+# 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.
+
+# Core Properties #
+nifi.flow.configuration.file=./target/flow.xml.gz
+nifi.flow.configuration.archive.dir=./target/archive/
+nifi.flowcontroller.autoResumeState=true
+nifi.flowcontroller.graceful.shutdown.period=10 sec
+nifi.flowservice.writedelay.interval=2 sec
+nifi.administrative.yield.duration=30 sec
+
+nifi.reporting.task.configuration.file=./target/reporting-tasks.xml
+nifi.controller.service.configuration.file=./target/controller-services.xml
+nifi.templates.directory=./target/templates
+nifi.ui.banner.text=UI Banner Text
+nifi.ui.autorefresh.interval=30 sec
+nifi.nar.library.directory=./src/test/resources/lib/
+nifi.nar.library.autoload.directory=./target/extensions
+
+nifi.nar.working.directory=./target/work/nar/
+nifi.documentation.working.directory=./target/work/docs/components
+
+# H2 Settings
+nifi.database.directory=./target/database_repository
+nifi.h2.url.append=;LOCK_TIMEOUT=25000;WRITE_DELAY=0;AUTO_SERVER=FALSE
+
+# FlowFile Repository
+nifi.flowfile.repository.directory=./target/test-repo
+nifi.flowfile.repository.partitions=1
+nifi.flowfile.repository.checkpoint.interval=2 mins
+nifi.queue.swap.threshold=20000
+nifi.swap.storage.directory=./target/test-repo/swap
+nifi.swap.in.period=5 sec
+nifi.swap.in.threads=1
+nifi.swap.out.period=5 sec
+nifi.swap.out.threads=4
+
+# Content Repository
+nifi.content.claim.max.appendable.size=10 MB
+nifi.content.claim.max.flow.files=100
+nifi.content.repository.directory.default=./target/content_repository
+
+# Provenance Repository Properties
+nifi.provenance.repository.storage.directory=./target/provenance_repository
+nifi.provenance.repository.max.storage.time=24 hours
+nifi.provenance.repository.max.storage.size=1 GB
+nifi.provenance.repository.rollover.time=30 secs
+nifi.provenance.repository.rollover.size=100 MB
+
+# Site to Site properties
+nifi.remote.input.socket.port=9990
+nifi.remote.input.secure=true
+
+# web properties #
+nifi.web.war.directory=./target/lib
+nifi.web.http.host=
+nifi.web.http.port=8080
+nifi.web.https.host=
+nifi.web.https.port=
+nifi.web.jetty.working.directory=./target/work/jetty
+
+# security properties #
+nifi.sensitive.props.key=key
+nifi.sensitive.props.algorithm=PBEWITHMD5AND256BITAES-CBC-OPENSSL
+nifi.sensitive.props.provider=BC
+
+nifi.security.keystore=
+nifi.security.keystoreType=
+nifi.security.keystorePasswd=
+nifi.security.keyPasswd=
+nifi.security.truststore=
+nifi.security.truststoreType=
+nifi.security.truststorePasswd=
+nifi.security.user.authorizer=
+
+# cluster common properties (cluster manager and nodes must have same values) #
+nifi.cluster.protocol.heartbeat.interval=5 sec
+nifi.cluster.protocol.is.secure=false
+nifi.cluster.protocol.socket.timeout=30 sec
+nifi.cluster.protocol.connection.handshake.timeout=45 sec
+# if multicast is used, then nifi.cluster.protocol.multicast.xxx properties must be configured #
+nifi.cluster.protocol.use.multicast=false
+nifi.cluster.protocol.multicast.address=
+nifi.cluster.protocol.multicast.port=
+nifi.cluster.protocol.multicast.service.broadcast.delay=500 ms
+nifi.cluster.protocol.multicast.service.locator.attempts=3
+nifi.cluster.protocol.multicast.service.locator.attempts.delay=1 sec
+
+# cluster node properties (only configure for cluster nodes) #
+nifi.cluster.is.node=false
+nifi.cluster.node.address=
+nifi.cluster.node.protocol.port=
+nifi.cluster.node.protocol.threads=2
+# if multicast is not used, nifi.cluster.node.unicast.xxx must have same values as nifi.cluster.manager.xxx #
+nifi.cluster.node.unicast.manager.address=
+nifi.cluster.node.unicast.manager.protocol.port=
+nifi.cluster.node.unicast.manager.authority.provider.port=
+
+# cluster manager properties (only configure for cluster manager) #
+nifi.cluster.is.manager=false
+nifi.cluster.manager.address=
+nifi.cluster.manager.protocol.port=
+nifi.cluster.manager.authority.provider.port=
+nifi.cluster.manager.authority.provider.threads=10
+nifi.cluster.manager.node.firewall.file=
+nifi.cluster.manager.node.event.history.size=10
+nifi.cluster.manager.node.api.connection.timeout=30 sec
+nifi.cluster.manager.node.api.read.timeout=30 sec
+nifi.cluster.manager.node.api.request.threads=10
+nifi.cluster.manager.flow.retrieval.delay=5 sec
+nifi.cluster.manager.protocol.threads=10
+nifi.cluster.manager.safemode.duration=0 sec
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/extensions/nifi-example-processors-nar-1.0.nar
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/extensions/nifi-example-processors-nar-1.0.nar b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/extensions/nifi-example-processors-nar-1.0.nar
new file mode 100644
index 0000000..317024a
Binary files /dev/null and b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/extensions/nifi-example-processors-nar-1.0.nar differ
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/extensions/nifi-example-service-api-nar-1.0.nar
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/extensions/nifi-example-service-api-nar-1.0.nar b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/extensions/nifi-example-service-api-nar-1.0.nar
new file mode 100644
index 0000000..a540b2d
Binary files /dev/null and b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/extensions/nifi-example-service-api-nar-1.0.nar differ
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/extensions/nifi-example-service-nar-1.1.nar
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/extensions/nifi-example-service-nar-1.1.nar b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/extensions/nifi-example-service-nar-1.1.nar
new file mode 100644
index 0000000..82f02a0
Binary files /dev/null and b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/extensions/nifi-example-service-nar-1.1.nar differ
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/lib/nifi-framework-nar.nar
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/lib/nifi-framework-nar.nar b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/lib/nifi-framework-nar.nar
new file mode 100644
index 0000000..0d0319b
Binary files /dev/null and b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/lib/nifi-framework-nar.nar differ
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/lib/nifi-jetty-bundle.nar
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/lib/nifi-jetty-bundle.nar b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/lib/nifi-jetty-bundle.nar
new file mode 100644
index 0000000..6fb2c5f
Binary files /dev/null and b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/lib/nifi-jetty-bundle.nar differ
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/nifi-example-nars-source.zip
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/nifi-example-nars-source.zip b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/nifi-example-nars-source.zip
new file mode 100644
index 0000000..e4477a5
Binary files /dev/null and b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-loading-utils/src/test/resources/nifi-example-nars-source.zip differ
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/init/ConfigurableComponentInitializerFactory.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/init/ConfigurableComponentInitializerFactory.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/init/ConfigurableComponentInitializerFactory.java
index f6ab922..61d1073 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/init/ConfigurableComponentInitializerFactory.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/init/ConfigurableComponentInitializerFactory.java
@@ -18,6 +18,7 @@ package org.apache.nifi.init;
import org.apache.nifi.components.ConfigurableComponent;
import org.apache.nifi.controller.ControllerService;
+import org.apache.nifi.nar.ExtensionManager;
import org.apache.nifi.processor.Processor;
import org.apache.nifi.reporting.ReportingTask;
@@ -30,13 +31,14 @@ public class ConfigurableComponentInitializerFactory {
* @param componentClass the class that requires a ConfigurableComponentInitializer
* @return a ConfigurableComponentInitializer capable of initializing that specific type of class
*/
- public static ConfigurableComponentInitializer createComponentInitializer(final Class<? extends ConfigurableComponent> componentClass) {
+ public static ConfigurableComponentInitializer createComponentInitializer(
+ final ExtensionManager extensionManager, final Class<? extends ConfigurableComponent> componentClass) {
if (Processor.class.isAssignableFrom(componentClass)) {
- return new ProcessorInitializer();
+ return new ProcessorInitializer(extensionManager);
} else if (ControllerService.class.isAssignableFrom(componentClass)) {
- return new ControllerServiceInitializer();
+ return new ControllerServiceInitializer(extensionManager);
} else if (ReportingTask.class.isAssignableFrom(componentClass)) {
- return new ReportingTaskingInitializer();
+ return new ReportingTaskingInitializer(extensionManager);
}
return null;
http://git-wip-us.apache.org/repos/asf/nifi/blob/fdd8cdbb/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/init/ControllerServiceInitializer.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/init/ControllerServiceInitializer.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/init/ControllerServiceInitializer.java
index 21b107f..1c3f136 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/init/ControllerServiceInitializer.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/init/ControllerServiceInitializer.java
@@ -35,25 +35,31 @@ import org.apache.nifi.reporting.InitializationException;
*/
public class ControllerServiceInitializer implements ConfigurableComponentInitializer {
+ private final ExtensionManager extensionManager;
+
+ public ControllerServiceInitializer(final ExtensionManager extensionManager) {
+ this.extensionManager = extensionManager;
+ }
+
@Override
public void initialize(ConfigurableComponent component) throws InitializationException {
ControllerService controllerService = (ControllerService) component;
ControllerServiceInitializationContext context = new MockControllerServiceInitializationContext();
- try (NarCloseable narCloseable = NarCloseable.withComponentNarLoader(component.getClass(), context.getIdentifier())) {
+ try (NarCloseable narCloseable = NarCloseable.withComponentNarLoader(extensionManager, component.getClass(), context.getIdentifier())) {
controllerService.initialize(context);
}
}
@Override
public void teardown(ConfigurableComponent component) {
- try (NarCloseable narCloseable = NarCloseable.withComponentNarLoader(component.getClass(), component.getIdentifier())) {
+ try (NarCloseable narCloseable = NarCloseable.withComponentNarLoader(extensionManager, component.getClass(), component.getIdentifier())) {
ControllerService controllerService = (ControllerService) component;
final ComponentLog logger = new MockComponentLogger();
final MockConfigurationContext context = new MockConfigurationContext();
ReflectionUtils.quietlyInvokeMethodsWithAnnotation(OnShutdown.class, controllerService, logger, context);
} finally {
- ExtensionManager.removeInstanceClassLoader(component.getIdentifier());
+ extensionManager.removeInstanceClassLoader(component.getIdentifier());
}
}
}