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

org.yamcs.PluginManager Maven / Gradle / Ivy

There is a newer version: 5.10.9
Show newest version
package org.yamcs;

import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.ServiceLoader;

import org.yamcs.Spec.OptionType;
import org.yamcs.logging.Log;
import org.yaml.snakeyaml.Yaml;

/**
 * Controls the loading of Yamcs plugins.
 */
public class PluginManager {

    private static final Log log = new Log(PluginManager.class);

    private Map, PluginMetadata> metadata = new HashMap<>();
    private Map, Plugin> plugins = new HashMap<>();

    public PluginManager() throws IOException {
        var yamcs = YamcsServer.getServer();
        for (var plugin : ServiceLoader.load(Plugin.class)) {
            var propsResource = "/META-INF/yamcs/" + plugin.getClass().getName() + "/plugin.properties";
            var props = new Properties();
            try (var in = getClass().getResourceAsStream(propsResource)) {
                props.load(in);
            }

            var pluginMetadata = new PluginMetadata(props);
            metadata.put(plugin.getClass(), pluginMetadata);

            var discoveredSpecs = discoverPluginOptions(plugin.getClass());

            // Plugins may programmatically define a spec, but default to
            // autodiscovery based on a resource descriptor.
            var spec = plugin.getSpec();
            if (spec == null) {
                spec = discoveredSpecs.globalSpec;
            }

            // Allow to disable any plugin
            spec.addOption("enabled", OptionType.BOOLEAN).withDefault(true);

            yamcs.addConfigurationSection(ConfigScope.YAMCS, pluginMetadata.getName(), spec);

            spec = plugin.getInstanceSpec();
            if (spec == null) {
                spec = discoveredSpecs.instanceSpec;
            }
            yamcs.addConfigurationSection(ConfigScope.YAMCS_INSTANCE, pluginMetadata.getName(), spec);
        }
    }

    @SuppressWarnings("unchecked")
    private PluginSpecs discoverPluginOptions(Class pluginClass) throws IOException {
        var specs = new PluginSpecs();
        try (var in = pluginClass.getResourceAsStream(pluginClass.getSimpleName() + ".yaml")) {
            if (in != null) {
                var yaml = new Yaml();
                Map pluginDescriptor = yaml.load(in);
                if (pluginDescriptor.containsKey("options")) {
                    var optionDescriptors = (Map>) pluginDescriptor
                            .get("options");
                    try {
                        specs.globalSpec = Spec.fromDescriptor(optionDescriptors);
                    } catch (ValidationException e) {
                        // Plugin error. Just throw it up because it must be fixed.
                        throw new RuntimeException(e);
                    }
                }
                if (pluginDescriptor.containsKey("instanceOptions")) {
                    var optionDescriptors = (Map>) pluginDescriptor
                            .get("instanceOptions");
                    try {
                        specs.instanceSpec = Spec.fromDescriptor(optionDescriptors);
                    } catch (ValidationException e) {
                        // Plugin error. Just throw it up because it must be fixed.
                        throw new RuntimeException(e);
                    }
                }
            }
        }
        return specs;
    }

    public Collection getPlugins() {
        return plugins.values();
    }

    @SuppressWarnings("unchecked")
    public  T getPlugin(Class clazz) {
        return (T) plugins.get(clazz);
    }

    public  PluginMetadata getMetadata(Class clazz) {
        return metadata.get(clazz);
    }

    public void discoverPlugins() {
        List disabledPlugins;
        YConfiguration yconf = YConfiguration.getConfiguration("yamcs");
        if (yconf.containsKey("disabledPlugins")) {
            disabledPlugins = yconf.getList("disabledPlugins");
        } else {
            disabledPlugins = Collections.emptyList();
        }

        for (var plugin : ServiceLoader.load(Plugin.class)) {
            var meta = metadata.get(plugin.getClass());
            if (disabledPlugins.contains(meta.getName())) {
                log.debug("Ignoring plugin {} (disabled by user config)", meta.getName());
            } else {
                var pluginConfig = yconf.getConfigOrEmpty(meta.getName());
                if (pluginConfig.getBoolean("enabled", true)) {
                    plugins.put(plugin.getClass(), plugin);
                } else {
                    log.debug("Ignoring plugin {} (disabled by user config)", meta.getName());
                }
            }
        }
    }

    public void loadPlugins() throws PluginException {
        var yamcsConfig = YamcsServer.getServer().getConfig();
        for (var plugin : plugins.values()) {
            var meta = metadata.get(plugin.getClass());
            log.debug("Loading plugin {} {}", meta.getName(), meta.getVersion());
            try {
                var config = yamcsConfig.getConfigOrEmpty(meta.getName());
                plugin.onLoad(config);
            } catch (PluginException e) {
                log.error("Could not load plugin {} {}", meta.getName(), meta.getVersion());
                throw e;
            }
        }
    }

    private static class PluginSpecs {
        Spec globalSpec = new Spec();
        Spec instanceSpec = new Spec();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy