This is an automated email from the ASF dual-hosted git repository.
markap14 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nifi.git
The following commit(s) were added to refs/heads/master by this push:
new 4b45e85 NIFI-6055 Improving error handling during auto-loading of
NARs and ensuring only one Jetty NAR is loaded
4b45e85 is described below
commit 4b45e85327bfb47669c09cde0c59c58812365998
Author: Bryan Bende <[email protected]>
AuthorDate: Wed Feb 20 10:38:46 2019 -0500
NIFI-6055 Improving error handling during auto-loading of NARs and ensuring
only one Jetty NAR is loaded
NIFI-6056 Fixing cassandra bundle so nifi-mock is a test scoped and
removing incorrect usage of ProviderCreation exception from nifi-framework-api
This closes #3322.
Signed-off-by: Mark Payne <[email protected]>
---
.../nifi-cassandra-processors/pom.xml | 7 ++-
.../cassandra/AbstractCassandraProcessor.java | 3 +-
.../cassandra/AbstractCassandraProcessorTest.java | 3 +-
.../org/apache/nifi/nar/StandardNarLoader.java | 7 ++-
.../nar/StandardExtensionDiscoveringManager.java | 58 ++++++++++++---------
.../java/org/apache/nifi/nar/NarUnpackerTest.java | 19 +++++--
.../NarUnpacker/lib/nifi-jetty-bundle.nar | Bin 0 -> 475 bytes
.../main/java/org/apache/nifi/nar/NarUnpacker.java | 37 +++++++++----
nifi-nar-bundles/pom.xml | 12 +++++
9 files changed, 98 insertions(+), 48 deletions(-)
diff --git
a/nifi-nar-bundles/nifi-cassandra-bundle/nifi-cassandra-processors/pom.xml
b/nifi-nar-bundles/nifi-cassandra-bundle/nifi-cassandra-processors/pom.xml
index 5cd6010..5392b56 100644
--- a/nifi-nar-bundles/nifi-cassandra-bundle/nifi-cassandra-processors/pom.xml
+++ b/nifi-nar-bundles/nifi-cassandra-bundle/nifi-cassandra-processors/pom.xml
@@ -75,11 +75,14 @@
<artifactId>nifi-record</artifactId>
<scope>compile</scope>
</dependency>
+ <!-- test scoped in nar-bundles dependency management -->
+ <dependency>
+ <groupId>org.apache.nifi</groupId>
+ <artifactId>nifi-mock</artifactId>
+ </dependency>
<dependency>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-mock-record-utils</artifactId>
- <version>1.10.0-SNAPSHOT</version>
- <scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
diff --git
a/nifi-nar-bundles/nifi-cassandra-bundle/nifi-cassandra-processors/src/main/java/org/apache/nifi/processors/cassandra/AbstractCassandraProcessor.java
b/nifi-nar-bundles/nifi-cassandra-bundle/nifi-cassandra-processors/src/main/java/org/apache/nifi/processors/cassandra/AbstractCassandraProcessor.java
index 8444120..2e2b8a8 100644
---
a/nifi-nar-bundles/nifi-cassandra-bundle/nifi-cassandra-processors/src/main/java/org/apache/nifi/processors/cassandra/AbstractCassandraProcessor.java
+++
b/nifi-nar-bundles/nifi-cassandra-bundle/nifi-cassandra-processors/src/main/java/org/apache/nifi/processors/cassandra/AbstractCassandraProcessor.java
@@ -31,7 +31,6 @@ import org.apache.avro.Schema;
import org.apache.avro.SchemaBuilder;
import org.apache.commons.lang3.StringUtils;
import org.apache.nifi.annotation.lifecycle.OnScheduled;
-import org.apache.nifi.authentication.exception.ProviderCreationException;
import org.apache.nifi.cassandra.CassandraSessionProviderService;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.components.PropertyValue;
@@ -255,7 +254,7 @@ public abstract class AbstractCassandraProcessor extends
AbstractProcessor {
try {
clientAuth =
SSLContextService.ClientAuth.valueOf(rawClientAuth);
} catch (final IllegalArgumentException iae) {
- throw new
ProviderCreationException(String.format("Unrecognized client auth '%s'.
Possible values are [%s]",
+ throw new
IllegalStateException(String.format("Unrecognized client auth '%s'. Possible
values are [%s]",
rawClientAuth,
StringUtils.join(SslContextFactory.ClientAuth.values(), ", ")));
}
}
diff --git
a/nifi-nar-bundles/nifi-cassandra-bundle/nifi-cassandra-processors/src/test/java/org/apache/nifi/processors/cassandra/AbstractCassandraProcessorTest.java
b/nifi-nar-bundles/nifi-cassandra-bundle/nifi-cassandra-processors/src/test/java/org/apache/nifi/processors/cassandra/AbstractCassandraProcessorTest.java
index a2c64c7..4401cd9 100644
---
a/nifi-nar-bundles/nifi-cassandra-bundle/nifi-cassandra-processors/src/test/java/org/apache/nifi/processors/cassandra/AbstractCassandraProcessorTest.java
+++
b/nifi-nar-bundles/nifi-cassandra-bundle/nifi-cassandra-processors/src/test/java/org/apache/nifi/processors/cassandra/AbstractCassandraProcessorTest.java
@@ -23,7 +23,6 @@ import com.datastax.driver.core.Metadata;
import com.datastax.driver.core.Row;
import com.google.common.collect.Sets;
import org.apache.nifi.annotation.lifecycle.OnEnabled;
-import org.apache.nifi.authentication.exception.ProviderCreationException;
import org.apache.nifi.components.PropertyDescriptor;
import org.apache.nifi.controller.ConfigurationContext;
import org.apache.nifi.processor.ProcessContext;
@@ -233,7 +232,7 @@ public class AbstractCassandraProcessorTest {
assertNotNull(processor.getCluster());
}
- @Test(expected = ProviderCreationException.class)
+ @Test(expected = IllegalStateException.class)
public void testConnectToCassandraWithSSLBadClientAuth() throws Exception {
SSLContextService sslService = mock(SSLContextService.class);
when(sslService.getIdentifier()).thenReturn("ssl-context");
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
index 2ddca01..20b566b 100644
---
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
@@ -141,7 +141,12 @@ public class StandardNarLoader implements NarLoader {
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()});
+ LOGGER.error("Found a framework NAR, will not auto-load {}",
new Object[]{narFile.getAbsolutePath()});
+ return null;
+ }
+
+ if (NarClassLoaders.JETTY_NAR_ID.equals(narId)) {
+ LOGGER.error("Found a Jetty NAR, will not auto-load {}", new
Object[]{narFile.getAbsolutePath()});
return null;
}
diff --git
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/nar/StandardExtensionDiscoveringManager.java
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/nar/StandardExtensionDiscoveringManager.java
index 5ca7601..8567f32 100644
---
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/nar/StandardExtensionDiscoveringManager.java
+++
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/main/java/org/apache/nifi/nar/StandardExtensionDiscoveringManager.java
@@ -150,38 +150,44 @@ public class StandardExtensionDiscoveringManager
implements ExtensionDiscovering
final ServiceLoader<?> serviceLoader =
ServiceLoader.load(entry.getKey(), bundle.getClassLoader());
for (final Object o : serviceLoader) {
- // create a cache of temp ConfigurableComponent instances, the
initialize here has to happen before the checks below
- if ((isControllerService || isProcessor || isReportingTask) &&
o instanceof ConfigurableComponent) {
- final ConfigurableComponent configurableComponent =
(ConfigurableComponent) o;
- initializeTempComponent(configurableComponent);
-
- final String cacheKey =
getClassBundleKey(o.getClass().getCanonicalName(),
bundle.getBundleDetails().getCoordinate());
- tempComponentLookup.put(cacheKey,
(ConfigurableComponent)o);
- }
-
- // only consider extensions discovered directly in this bundle
- boolean registerExtension =
bundle.getClassLoader().equals(o.getClass().getClassLoader());
-
- if (registerExtension) {
- final Class extensionType = o.getClass();
- if (isControllerService &&
!checkControllerServiceEligibility(extensionType)) {
- registerExtension = false;
- logger.error(String.format(
- "Skipping Controller Service %s because it is
bundled with its supporting APIs and requires instance class loading.",
extensionType.getName()));
+ try {
+ // create a cache of temp ConfigurableComponent instances,
the initialize here has to happen before the checks below
+ if ((isControllerService || isProcessor ||
isReportingTask) && o instanceof ConfigurableComponent) {
+ final ConfigurableComponent configurableComponent =
(ConfigurableComponent) o;
+ initializeTempComponent(configurableComponent);
+
+ final String cacheKey =
getClassBundleKey(o.getClass().getCanonicalName(),
bundle.getBundleDetails().getCoordinate());
+ tempComponentLookup.put(cacheKey,
(ConfigurableComponent) o);
}
- final boolean canReferenceControllerService =
(isControllerService || isProcessor || isReportingTask) && o instanceof
ConfigurableComponent;
- if (canReferenceControllerService &&
!checkControllerServiceReferenceEligibility((ConfigurableComponent) o,
bundle.getClassLoader())) {
- registerExtension = false;
- logger.error(String.format(
- "Skipping component %s because it is bundled
with its referenced Controller Service APIs and requires instance class
loading.", extensionType.getName()));
- }
+ // only consider extensions discovered directly in this
bundle
+ boolean registerExtension =
bundle.getClassLoader().equals(o.getClass().getClassLoader());
if (registerExtension) {
- registerServiceClass(o.getClass(),
classNameBundleLookup, bundleCoordinateClassesLookup, bundle, entry.getValue());
+ final Class extensionType = o.getClass();
+ if (isControllerService &&
!checkControllerServiceEligibility(extensionType)) {
+ registerExtension = false;
+ logger.error(String.format(
+ "Skipping Controller Service %s because it
is bundled with its supporting APIs and requires instance class loading.",
extensionType.getName()));
+ }
+
+ final boolean canReferenceControllerService =
(isControllerService || isProcessor || isReportingTask) && o instanceof
ConfigurableComponent;
+ if (canReferenceControllerService &&
!checkControllerServiceReferenceEligibility((ConfigurableComponent) o,
bundle.getClassLoader())) {
+ registerExtension = false;
+ logger.error(String.format(
+ "Skipping component %s because it is
bundled with its referenced Controller Service APIs and requires instance class
loading.", extensionType.getName()));
+ }
+
+ if (registerExtension) {
+ registerServiceClass(o.getClass(),
classNameBundleLookup, bundleCoordinateClassesLookup, bundle, entry.getValue());
+ }
+ }
+ } catch (Exception e) {
+ logger.warn("Failed to register extension {} due to: {}" ,
new Object[]{o.getClass().getCanonicalName(), e.getMessage()});
+ if (logger.isDebugEnabled()) {
+ logger.debug("", e);
}
}
-
}
classLoaderBundleLookup.put(bundle.getClassLoader(), bundle);
diff --git
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/test/java/org/apache/nifi/nar/NarUnpackerTest.java
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/test/java/org/apache/nifi/nar/NarUnpackerTest.java
index ac666ca..cc7fe74 100644
---
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/test/java/org/apache/nifi/nar/NarUnpackerTest.java
+++
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/test/java/org/apache/nifi/nar/NarUnpackerTest.java
@@ -34,7 +34,9 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
+import java.util.Optional;
import java.util.Set;
+import java.util.stream.Stream;
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
import static org.junit.Assert.assertEquals;
@@ -100,6 +102,7 @@ public class NarUnpackerTest {
Set<String> expectedNars = new HashSet<>();
expectedNars.add("dummy-one.nar-unpacked");
expectedNars.add("dummy-two.nar-unpacked");
+ expectedNars.add("nifi-jetty-bundle.nar-unpacked");
assertEquals(expectedNars.size(), extensionFiles.length);
for (File extensionFile : extensionFiles) {
@@ -127,8 +130,12 @@ public class NarUnpackerTest {
final File extensionsWorkingDir =
properties.getExtensionsWorkingDirectory();
File[] extensionFiles = extensionsWorkingDir.listFiles();
- assertEquals(1, extensionFiles.length);
- assertEquals("dummy-one.nar-unpacked", extensionFiles[0].getName());
+ assertEquals(2, extensionFiles.length);
+
+ final Optional<File> foundDummyOne = Stream.of(extensionFiles)
+ .filter(f -> f.getName().equals("dummy-one.nar-unpacked"))
+ .findFirst();
+ assertTrue(foundDummyOne.isPresent());
}
@Test
@@ -151,8 +158,12 @@ public class NarUnpackerTest {
final File extensionsWorkingDir =
properties.getExtensionsWorkingDirectory();
File[] extensionFiles = extensionsWorkingDir.listFiles();
- assertEquals(1, extensionFiles.length);
- assertEquals("dummy-one.nar-unpacked", extensionFiles[0].getName());
+ assertEquals(2, extensionFiles.length);
+
+ final Optional<File> foundDummyOne = Stream.of(extensionFiles)
+ .filter(f -> f.getName().equals("dummy-one.nar-unpacked"))
+ .findFirst();
+ assertTrue(foundDummyOne.isPresent());
}
@Test
diff --git
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/test/resources/NarUnpacker/lib/nifi-jetty-bundle.nar
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/test/resources/NarUnpacker/lib/nifi-jetty-bundle.nar
new file mode 100644
index 0000000..2adca76
Binary files /dev/null and
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-framework-nar-utils/src/test/resources/NarUnpacker/lib/nifi-jetty-bundle.nar
differ
diff --git
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-nar-utils/src/main/java/org/apache/nifi/nar/NarUnpacker.java
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-nar-utils/src/main/java/org/apache/nifi/nar/NarUnpacker.java
index edb824f..8bc163c 100644
---
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-nar-utils/src/main/java/org/apache/nifi/nar/NarUnpacker.java
+++
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-nar-utils/src/main/java/org/apache/nifi/nar/NarUnpacker.java
@@ -16,6 +16,14 @@
*/
package org.apache.nifi.nar;
+import org.apache.nifi.bundle.Bundle;
+import org.apache.nifi.bundle.BundleCoordinate;
+import org.apache.nifi.util.FileUtils;
+import org.apache.nifi.util.NiFiProperties;
+import org.apache.nifi.util.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.io.BufferedReader;
import java.io.File;
import java.io.FileFilter;
@@ -41,13 +49,6 @@ import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
-import org.apache.nifi.bundle.Bundle;
-import org.apache.nifi.bundle.BundleCoordinate;
-import org.apache.nifi.util.FileUtils;
-import org.apache.nifi.util.NiFiProperties;
-import org.apache.nifi.util.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
*
@@ -72,6 +73,7 @@ public final class NarUnpacker {
final Map<File, BundleCoordinate> unpackedNars = new HashMap<>();
try {
+ File unpackedJetty = null;
File unpackedFramework = null;
final Set<File> unpackedExtensions = new HashSet<>();
final List<File> narFiles = new ArrayList<>();
@@ -119,13 +121,19 @@ public final class NarUnpacker {
// unpack the framework nar
unpackedFramework = unpackNar(narFile,
frameworkWorkingDir);
+ } else if (NarClassLoaders.JETTY_NAR_ID.equals(narId))
{
+ if (unpackedJetty != null) {
+ throw new IllegalStateException("Multiple
Jetty NARs discovered. Only one Jetty NAR is permitted.");
+ }
+
+ // unpack and record the Jetty nar
+ unpackedJetty = unpackNar(narFile,
extensionsWorkingDir);
+ unpackedNars.put(unpackedJetty, new
BundleCoordinate(groupId, narId, version));
+ unpackedExtensions.add(unpackedJetty);
} else {
+ // unpack and record the extension nar
final File unpackedExtension = unpackNar(narFile,
extensionsWorkingDir);
-
- // record the current bundle
unpackedNars.put(unpackedExtension, new
BundleCoordinate(groupId, narId, version));
-
- // unpack the extension nar
unpackedExtensions.add(unpackedExtension);
}
}
@@ -138,6 +146,13 @@ public final class NarUnpacker {
throw new IllegalStateException("Framework NAR cannot be
read.");
}
+ // ensure we've found the jetty nar
+ if (unpackedJetty == null) {
+ throw new IllegalStateException("No Jetty NAR found.");
+ } else if (!unpackedJetty.canRead()) {
+ throw new IllegalStateException("Jetty NAR cannot be
read.");
+ }
+
// Determine if any nars no longer exist and delete their
working directories. This happens
// if a new version of a nar is dropped into the lib dir.
ensure no old framework are present
final File[] frameworkWorkingDirContents =
frameworkWorkingDir.listFiles();
diff --git a/nifi-nar-bundles/pom.xml b/nifi-nar-bundles/pom.xml
index 6b4027b..0b2e644 100755
--- a/nifi-nar-bundles/pom.xml
+++ b/nifi-nar-bundles/pom.xml
@@ -257,6 +257,18 @@
<version>1.10.0-SNAPSHOT</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.nifi</groupId>
+ <artifactId>nifi-mock</artifactId>
+ <version>1.10.0-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.nifi</groupId>
+ <artifactId>nifi-mock-record-utils</artifactId>
+ <version>1.10.0-SNAPSHOT</version>
+ <scope>test</scope>
+ </dependency>
<!-- The following dependencies are marked provided because they
must be provided by the container. Nars can assume they are there-->
<dependency>
<groupId>org.apache.nifi</groupId>