All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.jvmbytes.spy.plugin.PluginLoader Maven / Gradle / Ivy

The newest version!
package com.jvmbytes.spy.plugin;

import com.jvmbytes.spy.inject.SpyInjector;
import com.jvmbytes.spy.plugin.loader.AbstractPluginClassLoader;
import com.jvmbytes.spy.plugin.loader.PluginClassloaderBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Closeable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.ServiceLoader;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author wongoo
 */
public final class PluginLoader {

    private static final Logger logger = LoggerFactory.getLogger(PluginLoader.class);

    private static final String[] defaultParentPackagePrefix = new String[]{
            "java.",
            "javax.",
            "com.jvmbytes.",
            "org.ow2",
            "org.slf4j"
    };

    private static final Map> PLUGIN_LISTEN_IDS =
            new ConcurrentHashMap>(32);
    private static final Map PLUGIN_CLASS_LOADERS =
            new ConcurrentHashMap(32);

    private static final ReentrantLock LOCK = new ReentrantLock(true);

    public static String pluginKey(String groupId, String artifactId) {
        return groupId + "@" + artifactId;
    }

    /**
     * load plugin
     */
    public static void load(String groupId, String artifactId) throws Exception {
        String key = pluginKey(groupId, artifactId);
        if (PLUGIN_LISTEN_IDS.containsKey(key)) {
            logger.debug("{} already loaded", key);
            return;
        }

        LOCK.lock();
        try {
            if (PLUGIN_LISTEN_IDS.containsKey(key)) {
                logger.debug("{} already loaded", key);
                return;
            }
            AbstractPluginClassLoader classLoader = PluginClassloaderBuilder.build(key);
            classLoader.setParentPackagePrefixes(defaultParentPackagePrefix);

            Iterator plugins = ServiceLoader.load(SpyPlugin.class, classLoader).iterator();
            Map ids = new HashMap(8);
            PLUGIN_LISTEN_IDS.put(key, ids);
            PLUGIN_CLASS_LOADERS.put(key, classLoader);

            HashSet allowPackages = new HashSet(8);
            allowPackages.addAll(Arrays.asList(defaultParentPackagePrefix));

            while (plugins.hasNext()) {
                SpyPlugin plugin = plugins.next();

                if (plugin.getParentPackagePrefixes() != null) {
                    allowPackages.addAll(Arrays.asList(plugin.getParentPackagePrefixes()));
                    classLoader.setParentPackagePrefixes(allowPackages.toArray(new String[0]));
                }

                String namespace = plugin.getNamespace();
                if (namespace == null) {
                    namespace = SpyInjector.DEFAULT_NAMESPACE;
                }

                int listenId = SpyInjector.inject(namespace,
                        plugin.getMatcher(),
                        plugin.getEventTypes(),
                        plugin.getEventListener());

                ids.put(plugin.getName(), listenId);
                logger.info("plugin {} loaded, listen id {}", plugin.getName(), listenId);
            }
        } finally {
            LOCK.unlock();
        }
    }

    /**
     * unload plugin
     */
    public static void unload(String groupId, String artifactId) throws Exception {
        String key = pluginKey(groupId, artifactId);
        if (!PLUGIN_LISTEN_IDS.containsKey(key)) {
            logger.debug("{} not loaded", key);
            return;
        }

        LOCK.lock();
        try {
            Map ids = PLUGIN_LISTEN_IDS.remove(key);
            if (ids != null) {
                for (String name : ids.keySet()) {
                    Integer id = ids.get(name);
                    SpyInjector.remove(id);
                    logger.info("plugin {} unloaded, listen id {}", name, id);
                }
            }

            ClassLoader classLoader = PLUGIN_CLASS_LOADERS.remove(key);
            closeClassloader(classLoader);
            System.gc();
        } finally {
            LOCK.unlock();
        }
    }

    private static void closeClassloader(ClassLoader classLoader) {
        if (classLoader == null) {
            return;
        }

        if (classLoader instanceof Closeable) {
            try {
                ((Closeable) classLoader).close();
            } catch (Throwable ignored) {
            }
            return;
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy