use of org.apache.nifi.nar.NarCloseable in project nifi by apache.
the class TestStandardProcessorNode method testUpdateOtherPropertyDoesNotImpactClasspath.
@Test
public void testUpdateOtherPropertyDoesNotImpactClasspath() throws MalformedURLException {
final MockReloadComponent reloadComponent = new MockReloadComponent();
final PropertyDescriptor classpathProp = new PropertyDescriptor.Builder().name("Classpath Resources").dynamicallyModifiesClasspath(true).addValidator(StandardValidators.NON_EMPTY_VALIDATOR).build();
final PropertyDescriptor otherProp = new PropertyDescriptor.Builder().name("My Property").addValidator(StandardValidators.NON_EMPTY_VALIDATOR).build();
final ModifiesClasspathProcessor processor = new ModifiesClasspathProcessor(Arrays.asList(classpathProp, otherProp));
final StandardProcessorNode procNode = createProcessorNode(processor, reloadComponent);
try (final NarCloseable narCloseable = NarCloseable.withComponentNarLoader(procNode.getProcessor().getClass(), procNode.getIdentifier())) {
// Should not have any of the test resources loaded at this point
final URL[] testResources = getTestResources();
for (URL testResource : testResources) {
if (containsResource(reloadComponent.getAdditionalUrls(), testResource)) {
fail("found resource that should not have been loaded");
}
}
// Simulate setting the properties of the processor to point to the test resources directory
final Map<String, String> properties = new HashMap<>();
properties.put(classpathProp.getName(), "src/test/resources/TestClasspathResources");
procNode.setProperties(properties);
// Should have all of the resources loaded into the InstanceClassLoader now
for (URL testResource : testResources) {
assertTrue(containsResource(reloadComponent.getAdditionalUrls(), testResource));
}
// Should pass validation
assertTrue(procNode.isValid());
// Simulate setting updating the other property which should not change the classpath
final Map<String, String> otherProperties = new HashMap<>();
otherProperties.put(otherProp.getName(), "foo");
procNode.setProperties(otherProperties);
// Should STILL have all of the resources loaded into the InstanceClassLoader now
for (URL testResource : testResources) {
assertTrue(containsResource(reloadComponent.getAdditionalUrls(), testResource));
}
// Should STILL pass validation
assertTrue(procNode.isValid());
// Lets update the classpath property and make sure the resources get updated
final Map<String, String> newClasspathProperties = new HashMap<>();
newClasspathProperties.put(classpathProp.getName(), "src/test/resources/TestClasspathResources/resource1.txt");
procNode.setProperties(newClasspathProperties);
// Should only have resource1 loaded now
assertTrue(containsResource(reloadComponent.getAdditionalUrls(), testResources[0]));
assertFalse(containsResource(reloadComponent.getAdditionalUrls(), testResources[1]));
assertFalse(containsResource(reloadComponent.getAdditionalUrls(), testResources[2]));
assertEquals(ModifiesClasspathProcessor.class.getCanonicalName(), reloadComponent.getNewType());
// Should STILL pass validation
assertTrue(procNode.isValid());
} finally {
ExtensionManager.removeInstanceClassLoader(procNode.getIdentifier());
}
}
use of org.apache.nifi.nar.NarCloseable in project nifi by apache.
the class TestStandardProcessorNode method testSomeNonExistentPropertiesDynamicallyModifyClasspath.
@Test
public void testSomeNonExistentPropertiesDynamicallyModifyClasspath() throws MalformedURLException {
final MockReloadComponent reloadComponent = new MockReloadComponent();
final PropertyDescriptor classpathProp1 = new PropertyDescriptor.Builder().name("Classpath Resource 1").dynamicallyModifiesClasspath(true).addValidator(StandardValidators.NON_EMPTY_VALIDATOR).build();
final PropertyDescriptor classpathProp2 = new PropertyDescriptor.Builder().name("Classpath Resource 2").dynamicallyModifiesClasspath(true).addValidator(StandardValidators.NON_EMPTY_VALIDATOR).build();
final ModifiesClasspathProcessor processor = new ModifiesClasspathProcessor(Arrays.asList(classpathProp1, classpathProp2));
final StandardProcessorNode procNode = createProcessorNode(processor, reloadComponent);
try (final NarCloseable narCloseable = NarCloseable.withComponentNarLoader(procNode.getProcessor().getClass(), procNode.getIdentifier())) {
// Should not have any of the test resources loaded at this point
final URL[] testResources = getTestResources();
for (URL testResource : testResources) {
if (containsResource(reloadComponent.getAdditionalUrls(), testResource)) {
fail("found resource that should not have been loaded");
}
}
// Simulate setting the properties pointing to two of the resources
final Map<String, String> properties = new HashMap<>();
properties.put(classpathProp1.getName(), "src/test/resources/TestClasspathResources/resource1.txt");
properties.put(classpathProp2.getName(), "src/test/resources/TestClasspathResources/DoesNotExist.txt");
procNode.setProperties(properties);
// Should have resources 1 and 3 loaded into the InstanceClassLoader now
assertTrue(containsResource(reloadComponent.getAdditionalUrls(), testResources[0]));
assertFalse(containsResource(reloadComponent.getAdditionalUrls(), testResources[1]));
assertFalse(containsResource(reloadComponent.getAdditionalUrls(), testResources[2]));
assertEquals(ModifiesClasspathProcessor.class.getCanonicalName(), reloadComponent.getNewType());
// Should pass validation
assertTrue(procNode.isValid());
} finally {
ExtensionManager.removeInstanceClassLoader(procNode.getIdentifier());
}
}
use of org.apache.nifi.nar.NarCloseable in project nifi by apache.
the class TestStandardProcessorNode method testPropertyModifiesClasspathWhenProcessorMissingAnnotation.
@Test
public void testPropertyModifiesClasspathWhenProcessorMissingAnnotation() throws MalformedURLException {
final MockReloadComponent reloadComponent = new MockReloadComponent();
final ModifiesClasspathNoAnnotationProcessor processor = new ModifiesClasspathNoAnnotationProcessor();
final StandardProcessorNode procNode = createProcessorNode(processor, reloadComponent);
try (final NarCloseable narCloseable = NarCloseable.withComponentNarLoader(procNode.getProcessor().getClass(), procNode.getIdentifier())) {
final Map<String, String> properties = new HashMap<>();
properties.put(ModifiesClasspathNoAnnotationProcessor.CLASSPATH_RESOURCE.getName(), "src/test/resources/TestClasspathResources/resource1.txt");
procNode.setProperties(properties);
final URL[] testResources = getTestResources();
assertTrue(containsResource(reloadComponent.getAdditionalUrls(), testResources[0]));
assertFalse(containsResource(reloadComponent.getAdditionalUrls(), testResources[1]));
assertFalse(containsResource(reloadComponent.getAdditionalUrls(), testResources[2]));
assertEquals(ModifiesClasspathNoAnnotationProcessor.class.getCanonicalName(), reloadComponent.getNewType());
// Should pass validation
assertTrue(procNode.isValid());
} finally {
ExtensionManager.removeInstanceClassLoader(procNode.getIdentifier());
}
}
use of org.apache.nifi.nar.NarCloseable in project nifi by apache.
the class StandardProcessGroup method removeControllerService.
@Override
public void removeControllerService(final ControllerServiceNode service) {
boolean removed = false;
writeLock.lock();
try {
final ControllerServiceNode existing = controllerServices.get(requireNonNull(service).getIdentifier());
if (existing == null) {
throw new IllegalStateException("ControllerService " + service.getIdentifier() + " is not a member of this Process Group");
}
service.verifyCanDelete();
try (final NarCloseable x = NarCloseable.withComponentNarLoader(service.getControllerServiceImplementation().getClass(), service.getIdentifier())) {
final ConfigurationContext configurationContext = new StandardConfigurationContext(service, controllerServiceProvider, null, variableRegistry);
ReflectionUtils.quietlyInvokeMethodsWithAnnotation(OnRemoved.class, service.getControllerServiceImplementation(), configurationContext);
}
for (final Map.Entry<PropertyDescriptor, String> entry : service.getProperties().entrySet()) {
final PropertyDescriptor descriptor = entry.getKey();
if (descriptor.getControllerServiceDefinition() != null) {
final String value = entry.getValue() == null ? descriptor.getDefaultValue() : entry.getValue();
if (value != null) {
final ControllerServiceNode referencedNode = getControllerService(value);
if (referencedNode != null) {
referencedNode.removeReference(service);
}
}
}
}
controllerServices.remove(service.getIdentifier());
onComponentModified();
// For any component that references this Controller Service, find the component's Process Group
// and notify the Process Group that a component has been modified. This way, we know to re-calculate
// whether or not the Process Group has local modifications.
service.getReferences().getReferencingComponents().stream().map(ConfiguredComponent::getProcessGroupIdentifier).filter(id -> !id.equals(getIdentifier())).forEach(groupId -> {
final ProcessGroup descendant = findProcessGroup(groupId);
if (descendant != null) {
descendant.onComponentModified();
}
});
flowController.getStateManagerProvider().onComponentRemoved(service.getIdentifier());
removed = true;
LOG.info("{} removed from {}", service, this);
} finally {
if (removed) {
try {
ExtensionManager.removeInstanceClassLoader(service.getIdentifier());
} catch (Throwable t) {
}
}
writeLock.unlock();
}
}
use of org.apache.nifi.nar.NarCloseable in project nifi by apache.
the class StandardProcessGroup method removeProcessor.
@Override
public void removeProcessor(final ProcessorNode processor) {
boolean removed = false;
final String id = requireNonNull(processor).getIdentifier();
writeLock.lock();
try {
if (!processors.containsKey(id)) {
throw new IllegalStateException(processor.getIdentifier() + " is not a member of this Process Group");
}
processor.verifyCanDelete();
for (final Connection conn : processor.getConnections()) {
conn.verifyCanDelete();
}
try (final NarCloseable x = NarCloseable.withComponentNarLoader(processor.getProcessor().getClass(), processor.getIdentifier())) {
final StandardProcessContext processContext = new StandardProcessContext(processor, controllerServiceProvider, encryptor, getStateManager(processor.getIdentifier()), () -> false);
ReflectionUtils.quietlyInvokeMethodsWithAnnotation(OnRemoved.class, processor.getProcessor(), processContext);
} catch (final Exception e) {
throw new ComponentLifeCycleException("Failed to invoke 'OnRemoved' methods of processor with id " + processor.getIdentifier(), e);
}
for (final Map.Entry<PropertyDescriptor, String> entry : processor.getProperties().entrySet()) {
final PropertyDescriptor descriptor = entry.getKey();
if (descriptor.getControllerServiceDefinition() != null) {
final String value = entry.getValue() == null ? descriptor.getDefaultValue() : entry.getValue();
if (value != null) {
final ControllerServiceNode serviceNode = controllerServiceProvider.getControllerServiceNode(value);
if (serviceNode != null) {
serviceNode.removeReference(processor);
}
}
}
}
processors.remove(id);
onComponentModified();
flowController.onProcessorRemoved(processor);
LogRepositoryFactory.getRepository(processor.getIdentifier()).removeAllObservers();
final StateManagerProvider stateManagerProvider = flowController.getStateManagerProvider();
scheduler.submitFrameworkTask(new Runnable() {
@Override
public void run() {
stateManagerProvider.onComponentRemoved(processor.getIdentifier());
}
});
// must copy to avoid a concurrent modification
final Set<Connection> copy = new HashSet<>(processor.getConnections());
for (final Connection conn : copy) {
removeConnection(conn);
}
removed = true;
LOG.info("{} removed from flow", processor);
} finally {
if (removed) {
try {
ExtensionManager.removeInstanceClassLoader(id);
} catch (Throwable t) {
}
}
writeLock.unlock();
}
}
Aggregations