[ 
https://issues.apache.org/jira/browse/NIFIREG-43?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16219345#comment-16219345
 ] 

ASF GitHub Bot commented on NIFIREG-43:
---------------------------------------

Github user kevdoran commented on a diff in the pull request:

    https://github.com/apache/nifi-registry/pull/27#discussion_r146961424
  
    --- Diff: 
nifi-registry-framework/src/main/java/org/apache/nifi/registry/extension/ExtensionManager.java
 ---
    @@ -0,0 +1,213 @@
    +/*
    + * 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 org.apache.commons.lang3.StringUtils;
    +import org.apache.nifi.registry.authorization.AccessPolicyProvider;
    +import org.apache.nifi.registry.authorization.Authorizer;
    +import org.apache.nifi.registry.authorization.UserGroupProvider;
    +import org.apache.nifi.registry.flow.FlowPersistenceProvider;
    +import org.apache.nifi.registry.properties.NiFiRegistryProperties;
    +import org.slf4j.Logger;
    +import org.slf4j.LoggerFactory;
    +import org.springframework.beans.factory.annotation.Autowired;
    +import org.springframework.stereotype.Component;
    +
    +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;
    +import java.util.LinkedList;
    +import java.util.List;
    +import java.util.Map;
    +import java.util.ServiceLoader;
    +import java.util.Set;
    +import java.util.concurrent.atomic.AtomicBoolean;
    +
    +@Component
    +public class ExtensionManager {
    +
    +    static final Logger LOGGER = 
LoggerFactory.getLogger(ExtensionManager.class);
    +
    +    private static final List<Class> EXTENSION_CLASSES;
    +    static {
    +        final List<Class> classes = new ArrayList<>();
    +        classes.add(FlowPersistenceProvider.class);
    +        classes.add(UserGroupProvider.class);
    +        classes.add(AccessPolicyProvider.class);
    +        classes.add(Authorizer.class);
    +        EXTENSION_CLASSES = Collections.unmodifiableList(classes);
    +    }
    +
    +    private final NiFiRegistryProperties properties;
    +    private final Map<String,ExtensionClassLoader> classLoaderMap = new 
HashMap<>();
    +    private final AtomicBoolean loaded = new AtomicBoolean(false);
    +
    +    @Autowired
    +    public ExtensionManager(final NiFiRegistryProperties properties) {
    +        this.properties = properties;
    +    }
    +
    +    @PostConstruct
    +    public synchronized void discoverExtensions() {
    +        if (!loaded.get()) {
    +            // get the list of class loaders to consider
    +            final List<ExtensionClassLoader> classLoaders = 
getClassLoaders();
    +
    +            // for each class loader, attempt to load each extension class 
using the ServiceLoader
    +            for (final ExtensionClassLoader extensionClassLoader : 
classLoaders) {
    +                for (final Class extensionClass : EXTENSION_CLASSES) {
    +                    loadExtensions(extensionClass, extensionClassLoader);
    +                }
    +            }
    +
    +            loaded.set(true);
    +        }
    +    }
    +
    +    public ClassLoader getExtensionClassLoader(final String 
canonicalClassName) {
    +        if (StringUtils.isBlank(canonicalClassName)) {
    +            throw new IllegalArgumentException("Class name can not be 
null");
    +        }
    +
    +        return classLoaderMap.get(canonicalClassName);
    +    }
    +
    +    /**
    +     * Loads implementations of the given extension class from the given 
class loader.
    +     *
    +     * @param extensionClass the extension/service class
    +     * @param extensionClassLoader the class loader to search
    +     */
    +    private void loadExtensions(final Class extensionClass, final 
ExtensionClassLoader extensionClassLoader) {
    +        final ServiceLoader<?> serviceLoader = 
ServiceLoader.load(extensionClass, extensionClassLoader);
    +        for (final Object o : serviceLoader) {
    +            final String extensionClassName = 
o.getClass().getCanonicalName();
    +            if (classLoaderMap.containsKey(extensionClassName)) {
    +                final String currDir = extensionClassLoader.getRootDir();
    +                final String existingDir = 
classLoaderMap.get(extensionClassName).getRootDir();
    +                LOGGER.warn("Skipping {} from {} which was already found 
in {}", new Object[]{extensionClassName, currDir, existingDir});
    +            } else {
    +                classLoaderMap.put(o.getClass().getCanonicalName(), 
extensionClassLoader);
    +            }
    +        }
    +    }
    +
    +    /**
    +     * Gets all of the class loaders to consider for loading extensions.
    +     *
    +     * Includes the class loader of the web-app running the framework, 
plus a class loader for each additional
    +     * directory specified in nifi-registry.properties.
    +     *
    +     * @return a list of extension class loaders
    +     */
    +    private List<ExtensionClassLoader> getClassLoaders() {
    +        final List<ExtensionClassLoader> classLoaders = new ArrayList<>();
    +
    +        // start with the class loader that loaded ExtensionManager, 
should be WebAppClassLoader for API WAR
    +        final ExtensionClassLoader frameworkClassLoader = new 
ExtensionClassLoader("system", new URL[0], this.getClass().getClassLoader());
    --- End diff --
    
    "system" -> "framework"


> Provide configurable extension directories
> ------------------------------------------
>
>                 Key: NIFIREG-43
>                 URL: https://issues.apache.org/jira/browse/NIFIREG-43
>             Project: NiFi Registry
>          Issue Type: Improvement
>            Reporter: Bryan Bende
>            Assignee: Bryan Bende
>            Priority: Minor
>             Fix For: 0.0.1
>
>
> We should provide a way to specify directories through 
> nifi-registry.properties, where each directory can contain all the JARs for a 
> given extension, such as an alternative flow persistence provider. This way 
> we can at least provider class loader isolation for each custom directory, 
> rather than adding everything to the lib directory.



--
This message was sent by Atlassian JIRA
(v6.4.14#64029)

Reply via email to