package org.dcache.missingfiles.plugins; import com.google.common.base.Splitter; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Required; import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.ServiceLoader; import dmg.cells.nucleus.EnvironmentAware; import org.dcache.util.NDC; import org.dcache.util.ConfigurationProperties; import static com.google.common.base.Predicates.compose; import static com.google.common.base.Predicates.equalTo; import static com.google.common.collect.Iterables.find; /** * This class represents one or more plugins that are used in concert to * process missing file notification. */ public class PluginChain implements EnvironmentAware { private static final Logger _log = LoggerFactory.getLogger(PluginChain.class); private static final ServiceLoader<PluginFactory> _factories = ServiceLoader.load(PluginFactory.class); private final List<PluginInstance> _plugins = new ArrayList<>(); private String _pluginList; private final ConfigurationProperties _properties = new ConfigurationProperties(); /** * Accept a comma-separated list of plugin names. These will be * instantiated to form the chain of plugins to process. */ @Required public void setPluginList(String plugins) { _pluginList = plugins; } public void init() { _plugins.clear(); Splitter splitter = Splitter.on(',').trimResults().omitEmptyStrings(); for(String name : splitter.split(_pluginList)) { NDC ndc = NDC.cloneNdc(); NDC.push(name); try { createPlugin(name); } finally { NDC.set(ndc); } } } private void createPlugin(String name) { try { PluginFactory factory = find(_factories, compose(equalTo(name), PluginFactory::getName)); Plugin plugin = factory.createPlugin(_properties); PluginInstance pi = new PluginInstance(name, plugin); _plugins.add(pi); } catch(NoSuchElementException e) { _log.error("Unknown plugin"); } catch(RuntimeException e) { _log.error("Failed to instantiate plugin: {}", e.getMessage()); } } @Required @Override public void setEnvironment(Map<String,Object> environment) { _properties.clear(); for(Map.Entry<String,Object> entry : environment.entrySet()) { Object value = entry.getValue(); if (value != null) { _properties.put(entry.getKey(), value.toString()); } } } public void accept(PluginVisitor visitor) { for(PluginInstance pi : _plugins) { NDC ndc = NDC.cloneNdc(); NDC.push(pi.getName()); try { if(!visitor.visit(pi.getPlugin())) { break; } } finally { NDC.set(ndc); } } } /** * Simple class to hold metadata about an instantiated plugin. */ private static class PluginInstance { private final Plugin _plugin; private final String _name; PluginInstance(String name, Plugin plugin) { _plugin = plugin; _name = name; } public String getName() { return _name; } public Plugin getPlugin() { return _plugin; } } }