This is an automated email from the ASF dual-hosted git repository. mcgilman pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/nifi-registry.git
The following commit(s) were added to refs/heads/master by this push: new c30245f NIFIREG-356 Fixing additional classpath resources for Authorizers and ensuring proper context ClassLoader is set c30245f is described below commit c30245f47d2e10fb34baaa13ded64f13fd553ea6 Author: Bryan Bende <bbe...@apache.org> AuthorDate: Fri Jan 31 13:29:55 2020 -0500 NIFIREG-356 Fixing additional classpath resources for Authorizers and ensuring proper context ClassLoader is set This closes #256 --- .../registry/extension/ExtensionClassLoader.java | 37 +++++ .../registry/extension/ExtensionCloseable.java | 7 + .../nifi/registry/extension/ExtensionManager.java | 19 +-- .../security/authorization/AuthorizerFactory.java | 152 ++++++++++++++------- .../registry/security/util/ClassLoaderUtils.java | 138 +++++++++++++++++++ .../authorization/AuthorizerFactorySpec.groovy | 3 +- .../provider/TestStandardProviderFactory.java | 14 +- .../provider/hook/TestScriptEventHookProvider.java | 6 +- 8 files changed, 305 insertions(+), 71 deletions(-) diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionClassLoader.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionClassLoader.java new file mode 100644 index 0000000..1411f29 --- /dev/null +++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionClassLoader.java @@ -0,0 +1,37 @@ +/* + * 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.registry.extension; + +import java.net.URL; +import java.net.URLClassLoader; + +/** + * Extend URLClassLoader to keep track of the root directory. + */ +public class ExtensionClassLoader extends URLClassLoader { + + private final String rootDir; + + public ExtensionClassLoader(final String rootDir, final URL[] urls, final ClassLoader parent) { + super(urls, parent); + this.rootDir = rootDir; + } + + public String getRootDir() { + return rootDir; + } +} diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionCloseable.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionCloseable.java index b24f950..0735f2c 100644 --- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionCloseable.java +++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionCloseable.java @@ -40,6 +40,13 @@ public class ExtensionCloseable implements Closeable { return closeable; } + public static ExtensionCloseable withClassLoader(final ClassLoader componentClassLoader) { + final ClassLoader current = Thread.currentThread().getContextClassLoader(); + final ExtensionCloseable closeable = new ExtensionCloseable(current); + Thread.currentThread().setContextClassLoader(componentClassLoader); + return closeable; + } + @Override public void close() throws IOException { if (toSet != null) { diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionManager.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionManager.java index 455c833..edb3350 100644 --- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionManager.java +++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionManager.java @@ -33,7 +33,6 @@ import javax.annotation.PostConstruct; import java.io.File; import java.net.MalformedURLException; import java.net.URL; -import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -88,7 +87,7 @@ public class ExtensionManager { } } - public ClassLoader getExtensionClassLoader(final String canonicalClassName) { + public ExtensionClassLoader getExtensionClassLoader(final String canonicalClassName) { if (StringUtils.isBlank(canonicalClassName)) { throw new IllegalArgumentException("Class name can not be null"); } @@ -199,20 +198,4 @@ public class ExtensionManager { return new ExtensionClassLoader(dir, urls, parentClassLoader); } - /** - * Extend URLClassLoader to keep track of the root directory. - */ - private static class ExtensionClassLoader extends URLClassLoader { - - private final String rootDir; - - public ExtensionClassLoader(final String rootDir, final URL[] urls, final ClassLoader parent) { - super(urls, parent); - this.rootDir = rootDir; - } - - public String getRootDir() { - return rootDir; - } - } } diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizerFactory.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizerFactory.java index a819e97..959e29e 100644 --- a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizerFactory.java +++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/authorization/AuthorizerFactory.java @@ -17,6 +17,7 @@ package org.apache.nifi.registry.security.authorization; import org.apache.commons.lang3.StringUtils; +import org.apache.nifi.registry.extension.ExtensionClassLoader; import org.apache.nifi.registry.extension.ExtensionCloseable; import org.apache.nifi.registry.extension.ExtensionManager; import org.apache.nifi.registry.properties.NiFiRegistryProperties; @@ -30,6 +31,7 @@ import org.apache.nifi.registry.security.authorization.generated.Authorizers; import org.apache.nifi.registry.security.authorization.generated.Prop; import org.apache.nifi.registry.security.exception.SecurityProviderCreationException; import org.apache.nifi.registry.security.exception.SecurityProviderDestructionException; +import org.apache.nifi.registry.security.util.ClassLoaderUtils; import org.apache.nifi.registry.security.util.XmlUtils; import org.apache.nifi.registry.service.RegistryService; import org.slf4j.Logger; @@ -55,7 +57,11 @@ import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -201,11 +207,12 @@ public class AuthorizerFactory implements UserGroupProviderLookup, AccessPolicyP // configure each authorizer for (final org.apache.nifi.registry.security.authorization.generated.Authorizer provider : authorizerConfiguration.getAuthorizer()) { + if (provider.getIdentifier().equals(authorizerIdentifier)) { + continue; + } final Authorizer instance = authorizers.get(provider.getIdentifier()); - final Class authorizerClass = instance instanceof WrappedAuthorizer - ? ((WrappedAuthorizer) instance).getBaseAuthorizer().getClass() - : instance.getClass(); - try (ExtensionCloseable extCloseable = ExtensionCloseable.withComponentClassLoader(extensionManager, authorizerClass)) { + final ClassLoader instanceClassLoader = instance.getClass().getClassLoader(); + try (final ExtensionCloseable extClosable = ExtensionCloseable.withClassLoader(instanceClassLoader)) { instance.onConfigured(loadAuthorizerConfiguration(provider.getIdentifier(), provider.getProperty())); } } @@ -216,7 +223,37 @@ public class AuthorizerFactory implements UserGroupProviderLookup, AccessPolicyP // ensure it was found if (authorizer == null) { throw new AuthorizerFactoryException(String.format("The specified authorizer '%s' could not be found.", authorizerIdentifier)); + } else { + // get the ClassLoader of the Authorizer before wrapping it with anything + final ClassLoader authorizerClassLoader = authorizer.getClass().getClassLoader(); + + // install integrity checks + authorizer = AuthorizerFactory.installIntegrityChecks(authorizer); + + // load the configuration context for the selected authorizer + AuthorizerConfigurationContext authorizerConfigurationContext = null; + for (final org.apache.nifi.registry.security.authorization.generated.Authorizer provider : authorizerConfiguration.getAuthorizer()) { + if (provider.getIdentifier().equals(authorizerIdentifier)) { + authorizerConfigurationContext = loadAuthorizerConfiguration(provider.getIdentifier(), provider.getProperty()); + break; + } + } + + if (authorizerConfigurationContext == null) { + throw new IllegalStateException("Unable to load configuration for authorizer with id: " + authorizerIdentifier); + } + + // configure the authorizer that is wrapped with integrity checks + // set the context ClassLoader the wrapped authorizer's ClassLoader + try (final ExtensionCloseable extClosable = ExtensionCloseable.withClassLoader(authorizerClassLoader)) { + authorizer.onConfigured(authorizerConfigurationContext); + } + + // wrap the integrity checked Authorizer with the FrameworkAuthorizer + authorizer = createFrameworkAuthorizer(authorizer); } + + } catch (AuthorizerFactoryException e) { throw e; } catch (Exception e) { @@ -281,7 +318,6 @@ public class AuthorizerFactory implements UserGroupProviderLookup, AccessPolicyP } private UserGroupProvider createUserGroupProvider(final String identifier, final String userGroupProviderClassName) throws Exception { - final UserGroupProvider instance; final ClassLoader classLoader = extensionManager.getExtensionClassLoader(userGroupProviderClassName); @@ -289,22 +325,24 @@ public class AuthorizerFactory implements UserGroupProviderLookup, AccessPolicyP throw new IllegalStateException("Extension not found in any of the configured class loaders: " + userGroupProviderClassName); } - // attempt to load the class - Class<?> rawUserGroupProviderClass = Class.forName(userGroupProviderClassName, true, classLoader); - Class<? extends UserGroupProvider> userGroupProviderClass = rawUserGroupProviderClass.asSubclass(UserGroupProvider.class); + try (final ExtensionCloseable closeable = ExtensionCloseable.withClassLoader(classLoader)) { + // attempt to load the class + Class<?> rawUserGroupProviderClass = Class.forName(userGroupProviderClassName, true, classLoader); + Class<? extends UserGroupProvider> userGroupProviderClass = rawUserGroupProviderClass.asSubclass(UserGroupProvider.class); - // otherwise create a new instance - Constructor constructor = userGroupProviderClass.getConstructor(); - instance = (UserGroupProvider) constructor.newInstance(); + // otherwise create a new instance + Constructor constructor = userGroupProviderClass.getConstructor(); + instance = (UserGroupProvider) constructor.newInstance(); - // method injection - performMethodInjection(instance, userGroupProviderClass); + // method injection + performMethodInjection(instance, userGroupProviderClass); - // field injection - performFieldInjection(instance, userGroupProviderClass); + // field injection + performFieldInjection(instance, userGroupProviderClass); - // call post construction lifecycle event - instance.initialize(new StandardAuthorizerInitializationContext(identifier, this, this, this)); + // call post construction lifecycle event + instance.initialize(new StandardAuthorizerInitializationContext(identifier, this, this, this)); + } return instance; } @@ -317,22 +355,24 @@ public class AuthorizerFactory implements UserGroupProviderLookup, AccessPolicyP throw new IllegalStateException("Extension not found in any of the configured class loaders: " + accessPolicyProviderClassName); } - // attempt to load the class - Class<?> rawAccessPolicyProviderClass = Class.forName(accessPolicyProviderClassName, true, classLoader); - Class<? extends AccessPolicyProvider> accessPolicyClass = rawAccessPolicyProviderClass.asSubclass(AccessPolicyProvider.class); + try (final ExtensionCloseable closeable = ExtensionCloseable.withClassLoader(classLoader)) { + // attempt to load the class + Class<?> rawAccessPolicyProviderClass = Class.forName(accessPolicyProviderClassName, true, classLoader); + Class<? extends AccessPolicyProvider> accessPolicyClass = rawAccessPolicyProviderClass.asSubclass(AccessPolicyProvider.class); - // otherwise create a new instance - Constructor constructor = accessPolicyClass.getConstructor(); - instance = (AccessPolicyProvider) constructor.newInstance(); + // otherwise create a new instance + Constructor constructor = accessPolicyClass.getConstructor(); + instance = (AccessPolicyProvider) constructor.newInstance(); - // method injection - performMethodInjection(instance, accessPolicyClass); + // method injection + performMethodInjection(instance, accessPolicyClass); - // field injection - performFieldInjection(instance, accessPolicyClass); + // field injection + performFieldInjection(instance, accessPolicyClass); - // call post construction lifecycle event - instance.initialize(new StandardAuthorizerInitializationContext(identifier, this, this, this)); + // call post construction lifecycle event + instance.initialize(new StandardAuthorizerInitializationContext(identifier, this, this, this)); + } return instance; } @@ -340,33 +380,51 @@ public class AuthorizerFactory implements UserGroupProviderLookup, AccessPolicyP private Authorizer createAuthorizer(final String identifier, final String authorizerClassName, final String classpathResources) throws Exception { final Authorizer instance; - final ClassLoader classLoader = extensionManager.getExtensionClassLoader(authorizerClassName); - if (classLoader == null) { + ClassLoader classLoader; + + final ExtensionClassLoader extensionClassLoader = extensionManager.getExtensionClassLoader(authorizerClassName); + if (extensionClassLoader == null) { throw new IllegalStateException("Extension not found in any of the configured class loaders: " + authorizerClassName); } - // attempt to load the class - Class<?> rawAuthorizerClass = Class.forName(authorizerClassName, true, classLoader); - Class<? extends Authorizer> authorizerClass = rawAuthorizerClass.asSubclass(Authorizer.class); + // if additional classpath resources were specified, replace with a new ClassLoader that contains + // the combined resources of the original ClassLoader + the additional resources + if (StringUtils.isNotEmpty(classpathResources)) { + logger.info(String.format("Replacing Authorizer ClassLoader for '%s' to include additional resources: %s", identifier, classpathResources)); + final URL[] originalUrls = extensionClassLoader.getURLs(); + final URL[] additionalUrls = ClassLoaderUtils.getURLsForClasspath(classpathResources, null, true); - // otherwise create a new instance - Constructor constructor = authorizerClass.getConstructor(); - instance = (Authorizer) constructor.newInstance(); + final Set<URL> combinedUrls = new HashSet<>(); + combinedUrls.addAll(Arrays.asList(originalUrls)); + combinedUrls.addAll(Arrays.asList(additionalUrls)); - // method injection - performMethodInjection(instance, authorizerClass); + final URL[] urls = combinedUrls.toArray(new URL[combinedUrls.size()]); + classLoader = new URLClassLoader(urls, extensionClassLoader.getParent()); + } else { + // no additional resources so just use the ExtensionClassLoader + classLoader = extensionClassLoader; + } + + try (final ExtensionCloseable closeable = ExtensionCloseable.withClassLoader(classLoader)) { + // attempt to load the class + Class<?> rawAuthorizerClass = Class.forName(authorizerClassName, true, classLoader); + Class<? extends Authorizer> authorizerClass = rawAuthorizerClass.asSubclass(Authorizer.class); - // field injection - performFieldInjection(instance, authorizerClass); + // otherwise create a new instance + Constructor constructor = authorizerClass.getConstructor(); + instance = (Authorizer) constructor.newInstance(); - // call post construction lifecycle event - instance.initialize(new StandardAuthorizerInitializationContext(identifier, this, this, this)); + // method injection + performMethodInjection(instance, authorizerClass); - // wrap the instance Authorizer with checks to ensure integrity of data - final Authorizer integrityCheckAuthorizer = installIntegrityChecks(instance); + // field injection + performFieldInjection(instance, authorizerClass); - // wrap the integrity checked Authorizer with the FrameworkAuthorizer - return createFrameworkAuthorizer(integrityCheckAuthorizer); + // call post construction lifecycle event + instance.initialize(new StandardAuthorizerInitializationContext(identifier, this, this, this)); + } + + return instance; } private Authorizer createFrameworkAuthorizer(final Authorizer baseAuthorizer) { diff --git a/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/util/ClassLoaderUtils.java b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/util/ClassLoaderUtils.java new file mode 100644 index 0000000..1f05cd3 --- /dev/null +++ b/nifi-registry-core/nifi-registry-framework/src/main/java/org/apache/nifi/registry/security/util/ClassLoaderUtils.java @@ -0,0 +1,138 @@ +/* + * 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.registry.security.util; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.File; +import java.io.FilenameFilter; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Set; + +public class ClassLoaderUtils { + + static final Logger LOGGER = LoggerFactory.getLogger(ClassLoaderUtils.class); + + public static ClassLoader getCustomClassLoader(String modulePath, ClassLoader parentClassLoader, FilenameFilter filenameFilter) throws MalformedURLException { + URL[] classpaths = getURLsForClasspath(modulePath, filenameFilter, false); + return createModuleClassLoader(classpaths, parentClassLoader); + } + + /** + * + * @param modulePath a module path to get URLs from, the module path may be + * a comma-separated list of paths + * @param filenameFilter a filter to apply when a module path is a directory + * and performs a listing, a null filter will return all matches + * @param suppressExceptions indicates whether to suppress exceptions + * @return an array of URL instances representing all of the modules + * resolved from processing modulePath + * @throws MalformedURLException if a module path does not exist + */ + public static URL[] getURLsForClasspath(String modulePath, FilenameFilter filenameFilter, boolean suppressExceptions) throws MalformedURLException { + return getURLsForClasspath(modulePath == null ? Collections.emptySet() : Collections.singleton(modulePath), filenameFilter, suppressExceptions); + } + + /** + * + * @param modulePaths one or modules paths to get URLs from, each module + * path may be a comma-separated list of paths + * @param filenameFilter a filter to apply when a module path is a directory + * and performs a listing, a null filter will return all matches + * @param suppressExceptions if true then all modules will attempt to be + * resolved even if some throw an exception, if false the first exception + * will be thrown + * @return an array of URL instances representing all of the modules + * resolved from processing modulePaths + * @throws MalformedURLException if a module path does not exist + */ + public static URL[] getURLsForClasspath(Set<String> modulePaths, FilenameFilter filenameFilter, boolean suppressExceptions) throws MalformedURLException { + // use LinkedHashSet to maintain the ordering that the incoming paths are processed + Set<String> modules = new LinkedHashSet<>(); + if (modulePaths != null) { + modulePaths.stream() + .flatMap(path -> Arrays.stream(path.split(","))) + .filter(path -> isNotBlank(path)) + .map(String::trim) + .forEach(m -> modules.add(m)); + } + return toURLs(modules, filenameFilter, suppressExceptions); + } + + private static boolean isNotBlank(final String value) { + return value != null && !value.trim().isEmpty(); + } + + protected static URL[] toURLs(Set<String> modulePaths, FilenameFilter filenameFilter, boolean suppressExceptions) throws MalformedURLException { + List<URL> additionalClasspath = new LinkedList<>(); + if (modulePaths != null) { + for (String modulePathString : modulePaths) { + // If the path is already a URL, just add it (but don't check if it exists, too expensive and subject to network availability) + boolean isUrl = true; + try { + additionalClasspath.add(new URL(modulePathString)); + } catch (MalformedURLException mue) { + isUrl = false; + } + if (!isUrl) { + try { + File modulePath = new File(modulePathString); + + if (modulePath.exists()) { + + additionalClasspath.add(modulePath.toURI().toURL()); + + if (modulePath.isDirectory()) { + File[] files = modulePath.listFiles(filenameFilter); + + if (files != null) { + for (File classpathResource : files) { + if (classpathResource.isDirectory()) { + LOGGER.warn("Recursive directories are not supported, skipping " + classpathResource.getAbsolutePath()); + } else { + additionalClasspath.add(classpathResource.toURI().toURL()); + } + } + } + } + } else { + throw new MalformedURLException("Path specified does not exist"); + } + } catch (MalformedURLException e) { + if (!suppressExceptions) { + throw e; + } + } + } + } + } + return additionalClasspath.toArray(new URL[additionalClasspath.size()]); + } + + protected static ClassLoader createModuleClassLoader(URL[] modules, ClassLoader parentClassLoader) { + return new URLClassLoader(modules, parentClassLoader); + } + +} diff --git a/nifi-registry-core/nifi-registry-framework/src/test/groovy/org/apache/nifi/registry/security/authorization/AuthorizerFactorySpec.groovy b/nifi-registry-core/nifi-registry-framework/src/test/groovy/org/apache/nifi/registry/security/authorization/AuthorizerFactorySpec.groovy index 34dfe6b..bd79e55 100644 --- a/nifi-registry-core/nifi-registry-framework/src/test/groovy/org/apache/nifi/registry/security/authorization/AuthorizerFactorySpec.groovy +++ b/nifi-registry-core/nifi-registry-framework/src/test/groovy/org/apache/nifi/registry/security/authorization/AuthorizerFactorySpec.groovy @@ -16,6 +16,7 @@ */ package org.apache.nifi.registry.security.authorization +import org.apache.nifi.registry.extension.ExtensionClassLoader import org.apache.nifi.registry.extension.ExtensionManager import org.apache.nifi.registry.properties.NiFiRegistryProperties import org.apache.nifi.registry.security.authorization.resource.ResourceFactory @@ -32,7 +33,7 @@ class AuthorizerFactorySpec extends Specification { // runs before every feature method def setup() { - mockExtensionManager.getExtensionClassLoader(_) >> this.getClass().getClassLoader() + mockExtensionManager.getExtensionClassLoader(_) >> new ExtensionClassLoader("/tmp", new URL[0],this.getClass().getClassLoader()) mockProperties.getPropertyKeys() >> new HashSet<String>() // Called by IdentityMappingUtil.getIdentityMappings() authorizerFactory = new AuthorizerFactory(mockProperties, mockExtensionManager, null, mockRegistryService) diff --git a/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/TestStandardProviderFactory.java b/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/TestStandardProviderFactory.java index 0d23110..7fb8dee 100644 --- a/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/TestStandardProviderFactory.java +++ b/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/TestStandardProviderFactory.java @@ -17,6 +17,7 @@ package org.apache.nifi.registry.provider; import org.apache.nifi.registry.extension.BundlePersistenceProvider; +import org.apache.nifi.registry.extension.ExtensionClassLoader; import org.apache.nifi.registry.extension.ExtensionManager; import org.apache.nifi.registry.flow.FlowPersistenceProvider; import org.apache.nifi.registry.properties.NiFiRegistryProperties; @@ -24,6 +25,7 @@ import org.junit.Test; import org.mockito.Mockito; import javax.sql.DataSource; +import java.net.URL; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; @@ -38,7 +40,8 @@ public class TestStandardProviderFactory { props.setProperty(NiFiRegistryProperties.PROVIDERS_CONFIGURATION_FILE, "src/test/resources/provider/providers-good.xml"); final ExtensionManager extensionManager = Mockito.mock(ExtensionManager.class); - when(extensionManager.getExtensionClassLoader(any(String.class))).thenReturn(this.getClass().getClassLoader()); + when(extensionManager.getExtensionClassLoader(any(String.class))) + .thenReturn(new ExtensionClassLoader("/tmp", new URL[0],this.getClass().getClassLoader())); final DataSource dataSource = Mockito.mock(DataSource.class); @@ -68,7 +71,8 @@ public class TestStandardProviderFactory { props.setProperty(NiFiRegistryProperties.PROVIDERS_CONFIGURATION_FILE, "src/test/resources/provider/providers-good.xml"); final ExtensionManager extensionManager = Mockito.mock(ExtensionManager.class); - when(extensionManager.getExtensionClassLoader(any(String.class))).thenReturn(this.getClass().getClassLoader()); + when(extensionManager.getExtensionClassLoader(any(String.class))) + .thenReturn(new ExtensionClassLoader("/tmp", new URL[0],this.getClass().getClassLoader())); final DataSource dataSource = Mockito.mock(DataSource.class); @@ -82,7 +86,8 @@ public class TestStandardProviderFactory { props.setProperty(NiFiRegistryProperties.PROVIDERS_CONFIGURATION_FILE, "src/test/resources/provider/providers-does-not-exist.xml"); final ExtensionManager extensionManager = Mockito.mock(ExtensionManager.class); - when(extensionManager.getExtensionClassLoader(any(String.class))).thenReturn(this.getClass().getClassLoader()); + when(extensionManager.getExtensionClassLoader(any(String.class))) + .thenReturn(new ExtensionClassLoader("/tmp", new URL[0],this.getClass().getClassLoader())); final DataSource dataSource = Mockito.mock(DataSource.class); @@ -96,7 +101,8 @@ public class TestStandardProviderFactory { props.setProperty(NiFiRegistryProperties.PROVIDERS_CONFIGURATION_FILE, "src/test/resources/provider/providers-class-not-found.xml"); final ExtensionManager extensionManager = Mockito.mock(ExtensionManager.class); - when(extensionManager.getExtensionClassLoader(any(String.class))).thenReturn(this.getClass().getClassLoader()); + when(extensionManager.getExtensionClassLoader(any(String.class))) + .thenReturn(new ExtensionClassLoader("/tmp", new URL[0],this.getClass().getClassLoader())); final DataSource dataSource = Mockito.mock(DataSource.class); diff --git a/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/hook/TestScriptEventHookProvider.java b/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/hook/TestScriptEventHookProvider.java index b7d241b..39d45ae 100644 --- a/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/hook/TestScriptEventHookProvider.java +++ b/nifi-registry-core/nifi-registry-framework/src/test/java/org/apache/nifi/registry/provider/hook/TestScriptEventHookProvider.java @@ -16,6 +16,7 @@ */ package org.apache.nifi.registry.provider.hook; +import org.apache.nifi.registry.extension.ExtensionClassLoader; import org.apache.nifi.registry.extension.ExtensionManager; import org.apache.nifi.registry.properties.NiFiRegistryProperties; import org.apache.nifi.registry.provider.ProviderCreationException; @@ -26,6 +27,8 @@ import org.mockito.Mockito; import javax.sql.DataSource; +import java.net.URL; + import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.when; @@ -37,7 +40,8 @@ public class TestScriptEventHookProvider { props.setProperty(NiFiRegistryProperties.PROVIDERS_CONFIGURATION_FILE, "src/test/resources/provider/hook/bad-script-provider.xml"); final ExtensionManager extensionManager = Mockito.mock(ExtensionManager.class); - when(extensionManager.getExtensionClassLoader(any(String.class))).thenReturn(this.getClass().getClassLoader()); + when(extensionManager.getExtensionClassLoader(any(String.class))) + .thenReturn(new ExtensionClassLoader("/tmp", new URL[0],this.getClass().getClassLoader())); final DataSource dataSource = Mockito.mock(DataSource.class);