Java tutorial
/* * (c) Kitodo. Key to digital objects e. V. <contact@kitodo.org> * * This file is part of the Kitodo project. * * It is licensed under GNU General Public License version 3 or later. * * For the full copyright and license information, please read the * GPL3-License.txt file that was distributed with this source code. */ package org.goobi.production.plugin; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Objects; import net.xeoh.plugins.base.Plugin; import net.xeoh.plugins.base.PluginManager; import net.xeoh.plugins.base.impl.PluginManagerFactory; import net.xeoh.plugins.base.util.PluginManagerUtil; import org.apache.commons.io.FilenameUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.goobi.production.enums.ImportType; import org.goobi.production.enums.PluginType; import org.goobi.production.plugin.catalogue.CataloguePlugin; import org.goobi.production.plugin.interfaces.IImportPlugin; import org.goobi.production.plugin.interfaces.IPlugin; import org.kitodo.config.ConfigCore; import org.kitodo.config.enums.ParameterCore; import org.kitodo.production.plugin.importer.massimport.PicaMassImport; /** * The class PluginLoader provides for the loading of plug-ins at runtime. * * @author Based on preceding works from authors not named * @author Matthias Ronge <matthias.ronge@zeutschel.de> */ public class PluginLoader { private static final Logger logger = LogManager.getLogger(PluginLoader.class); private static final short INTERNAL_CLASSES_COUNT = 4; private static final String INTERNAL_CLASSES_PREFIX = "net.xeoh.plugins."; /** * Private constructor to hide the implicit public one. */ private PluginLoader() { } /** * The function getCataloguePluginForCatalogue() returns a redirection class * to handle the first plug-in implementation object that positively * responds to <code>supportsCatalogue(catalogue)</code>. * * @param catalogue * catalogue in question * @return the first plug-in that supports the given catalogue */ public static CataloguePlugin getCataloguePluginForCatalogue(String catalogue) { for (CataloguePlugin plugin : PluginLoader.getPlugins(CataloguePlugin.class)) { if (plugin.supportsCatalogue(catalogue)) { return plugin; } } return null; } /** * Get plugin list. * * @deprecated Using this function is discouraged. Use * <code>getPlugins(Class)</code> instead. */ @Deprecated public static List<IPlugin> getPluginList(PluginType inType) { PluginManagerUtil pmu = getPluginLoader(inType); Collection<IPlugin> plugins = pmu.getPlugins(IPlugin.class); PicaMassImport pmi = new PicaMassImport(); plugins.add(pmi); return new ArrayList<>(plugins); } /** * Get plugin by title. * * @deprecated Using this function is discouraged. Use * <code>getPluginByTitle(Class, String, Locale)</code> instead. */ @Deprecated public static IPlugin getPluginByTitle(PluginType inType, String inTitle) { PluginManagerUtil pmu = getPluginLoader(inType); Collection<IPlugin> plugins = pmu.getPlugins(inType.getInterfaz()); PicaMassImport pmi = new PicaMassImport(); plugins.add(pmi); for (IPlugin p : plugins) { if (p.getTitle().equals(inTitle)) { return p; } } return null; } /** * The function getPluginByTitle() loads all plug-ins implementing the given * UnspecificPlugin class type and returns a redirection class to handle the * first plug-in implementation object that responds to * <code>getTitle(language)</code> with the given title. * * <p> * Currently, this method is not referenced from within the Production code, * but this may change in future. The function is provided to show how the * old plug-in API can be replaced in future. * </p> * * @param clazz * UnspecificPlugin class type of the plug-ins to load * @param title * title the plug-in implementation object shall respond with * @param language * language the title is in (may be null) * @return the first plug-in that responds with the given title */ public static <T extends UnspecificPlugin> T getPluginByTitle(Class<T> clazz, String title, Locale language) { for (T plugin : getPlugins(clazz)) { if (plugin.getTitle(language).equals(title)) { return plugin; } } return null; } @Deprecated public static IPlugin getPlugin(PluginType inType, String inTitle) { return getPluginByTitle(inType, inTitle); } /** * The function getPluginConfiguration() creates a HashMap that is passed to * the plug-ins upon creation to configure them. The plug-ins may or may not * make use of the configuration provided. * * <p> * This is intended to be used for <em>general</em> configuration (probably) * suitable for all plug-in types. Use setters on the plug-ins to set * type-specific settings. * </p> * * @return a HashMap to configure the plug-ins */ private static HashMap<String, String> getPluginConfiguration() { short entries = 2; HashMap<String, String> conf = new HashMap<>((int) Math.ceil(entries / 0.75)); conf.put("configDir", ConfigCore.getKitodoConfigDirectory()); conf.put("tempDir", ConfigCore.getParameter(ParameterCore.DIR_PLUGINS_TEMP)); return conf; } /** * The function getPlugins() loads all plug-ins implementing the given * UnspecificPlugin class type and returns a Collection of redirection * classes, each to handle one plug-in implementation object. * * @param clazz * UnspecificPlugin class type of the plug-ins to load * @return a Collection of plug-in redirection classes */ @SuppressWarnings("unchecked") public static <T extends UnspecificPlugin> Collection<T> getPlugins(Class<T> clazz) { ArrayList<T> result = new ArrayList<>(); PluginType type = UnspecificPlugin.typeOf(clazz); if (Objects.nonNull(type)) { PluginManagerUtil pluginLoader = getPluginLoader(type); Collection<Plugin> plugins = pluginLoader.getPlugins(Plugin.class); // Never API version supports no-arg getPlugins() TODO: update API result = new ArrayList<>(plugins.size() - INTERNAL_CLASSES_COUNT); for (Plugin implementation : plugins) { if (implementation.getClass().getName().startsWith(INTERNAL_CLASSES_PREFIX)) { continue; // Skip plugin API internal classes } try { T plugin = (T) UnspecificPlugin.create(type, implementation); plugin.configure(getPluginConfiguration()); result.add(plugin); } catch (NoSuchMethodException | SecurityException e) { logger.warn("Bad implementation of {} plugin {}. Exception: {}", type.getName(), implementation.getClass().getName(), e); } } } return result; } /** * The function getImportPluginsForType() returns a list of titles of import * plug-ins matching the given ImportType. * * @param type * ImportType of plug-ins to look for * @return a list of titles of import plug-ins matching */ public static List<String> getImportPluginsForType(ImportType type) { List<String> pluginList = new ArrayList<>(); for (IPlugin p : PluginLoader.getPluginList(PluginType.IMPORT)) { IImportPlugin ip = (IImportPlugin) p; if (ip.getImportTypes().contains(type)) { pluginList.add(p.getTitle()); } } return pluginList; } /** * The function getPluginLoader() returns a PluginManagerUtil suitable for * loading plug-ins from the subdirectory defined by the given PluginType. * * @param type * plug-in type specifying the plug-in subdirectory to scan * @return a PluginManagerUtil to load plug-ins from that directory */ private static PluginManagerUtil getPluginLoader(PluginType type) { PluginManager pluginManager = PluginManagerFactory.createPluginManager(); String path = FilenameUtils.concat(ConfigCore.getParameter(ParameterCore.DIR_PLUGINS), type.getName()); pluginManager.addPluginsFrom(new File(path).toURI()); return new PluginManagerUtil(pluginManager); } }