server
Clone or download
Modified Files
--- /dev/null
+++ b/src/main/java/com/stream_pi/server/action/ExternalPlugins.java
@@ -0,0 +1,572 @@
+/*
+Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macropad
+Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones)
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+Written by : Debayan Sutradhar (rnayabed)
+*/
+
+package com.stream_pi.server.action;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.Result;
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import com.stream_pi.action_api.action.Action;
+import com.stream_pi.action_api.action.ActionType;
+import com.stream_pi.action_api.action.PropertySaver;
+import com.stream_pi.action_api.action.ServerConnection;
+import com.stream_pi.action_api.actionproperty.ServerProperties;
+import com.stream_pi.action_api.actionproperty.property.Property;
+import com.stream_pi.action_api.actionproperty.property.Type;
+import com.stream_pi.action_api.normalaction.ExternalPlugin;
+import com.stream_pi.action_api.normalaction.NormalAction;
+import com.stream_pi.util.exception.MinorException;
+import com.stream_pi.util.exception.SevereException;
+import com.stream_pi.util.exception.StreamPiException;
+import com.stream_pi.util.version.Version;
+import com.stream_pi.util.xmlconfighelper.XMLConfigHelper;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import java.io.File;
+import java.lang.module.*;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ServiceLoader;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+
+import org.w3c.dom.Element;
+
+public class ExternalPlugins
+{
+ private static ExternalPlugins instance = null;
+ private final Logger logger;
+
+ private File configFile;
+ private Document document;
+
+ private static String pluginsLocation = null;
+
+
+ /**
+ * Singleton class instance getter. Creates new one, when asked for the first time
+ *
+ * @return returns instance of NormalActionPlugins (one and only, always)
+ */
+ public static synchronized ExternalPlugins getInstance()
+ {
+ if(instance == null)
+ {
+ instance = new ExternalPlugins();
+ }
+
+ return instance;
+ }
+
+ /**
+ * Sets the folder location where the plugin JARs and their dependencies are stored
+ *
+ * @param location Folder location
+ */
+ public static void setPluginsLocation(String location)
+ {
+ pluginsLocation = location;
+ }
+
+ /**
+ * Private constructor
+ */
+ private ExternalPlugins()
+ {
+ logger = Logger.getLogger(ExternalPlugins.class.getName());
+ externalPluginsHashmap = new HashMap<>();
+ }
+
+ /**
+ * init Method
+ */
+ public void init() throws SevereException, MinorException
+ {
+ registerPlugins();
+ initPlugins();
+ }
+
+ /**
+ * Used to fetch list of all external Plugins
+ *
+ * @return List of plugins
+ */
+ public List<ExternalPlugin> getPlugins()
+ {
+ return externalPlugins;
+ }
+
+ /**
+ * Returns a plugin by its module name
+ *
+ * @param name Module Name
+ * @return The plugin. If not found, then null is returned
+ */
+ public ExternalPlugin getPluginByModuleName(String name)
+ {
+ logger.info("Plugin being requested : "+name);
+ Integer index = externalPluginsHashmap.getOrDefault(name, -1);
+ if(index != -1)
+ {
+ return externalPlugins.get(index);
+ }
+
+ return null;
+ }
+
+ private List<ExternalPlugin> externalPlugins = null;
+ HashMap<String, Integer> externalPluginsHashmap;
+
+ /**
+ * Used to register plugins from plugin location
+ */
+ public void registerPlugins() throws SevereException, MinorException
+ {
+ logger.info("Registering external plugins from "+pluginsLocation+" ...");
+
+ try
+ {
+ configFile = new File(pluginsLocation+"/config.xml");
+ DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
+ document = docBuilder.parse(configFile);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ throw new SevereException("Plugins","Error reading plugins config.xml. Cannot continue.");
+ }
+
+ ArrayList<ExternalPlugin> errorModules = new ArrayList<>();
+ ArrayList<String> errorModuleError = new ArrayList<>();
+
+ ArrayList<Action> pluginsConfigs = new ArrayList<>();
+
+ NodeList actionsNode = document.getElementsByTagName("actions").item(0).getChildNodes();
+
+ for(int i =0;i<actionsNode.getLength();i++)
+ {
+ Node eachActionNode = actionsNode.item(i);
+
+ if(eachActionNode.getNodeType() != Node.ELEMENT_NODE)
+ continue;
+
+ if(!eachActionNode.getNodeName().equals("action"))
+ continue;
+
+ Element eachActionElement = (Element) eachActionNode;
+
+
+
+ String name;
+ Version version;
+ try
+ {
+ name = XMLConfigHelper.getStringProperty(eachActionElement, "module-name");
+ version = new Version(XMLConfigHelper.getStringProperty(eachActionElement, "version"));
+ }
+ catch (Exception e)
+ {
+ logger.log(Level.WARNING, "Skipping configuration because invalid ...");
+ e.printStackTrace();
+ continue;
+ }
+
+ ServerProperties serverProperties = new ServerProperties();
+
+ NodeList serverPropertiesNodeList = eachActionElement.getElementsByTagName("properties").item(0).getChildNodes();
+
+ for(int j = 0;j<serverPropertiesNodeList.getLength();j++)
+ {
+ Node eachPropertyNode = serverPropertiesNodeList.item(j);
+
+
+ if(eachPropertyNode.getNodeType() != Node.ELEMENT_NODE)
+ continue;
+
+ if(!eachPropertyNode.getNodeName().equals("property"))
+ continue;
+
+
+ Element eachPropertyElement = (Element) eachPropertyNode;
+
+ try
+ {
+ Property property = new Property(XMLConfigHelper.getStringProperty(eachPropertyElement, "name"), Type.STRING);
+ property.setRawValue(XMLConfigHelper.getStringProperty(eachPropertyElement, "value"));
+
+ serverProperties.addProperty(property);
+ }
+ catch (Exception e)
+ {
+ logger.log(Level.WARNING, "Skipping property because invalid ...");
+ e.printStackTrace();
+ }
+ }
+
+ Action action = new Action(ActionType.NORMAL);
+
+ action.setModuleName(name);
+ action.setVersion(version);
+ action.getServerProperties().set(serverProperties);
+
+ pluginsConfigs.add(action);
+ }
+
+ logger.info("Size : "+pluginsConfigs.size());
+
+ Path pluginsDir = Paths.get(pluginsLocation); // Directory with plugins JARs
+ try
+ {
+ // Search for plugins in the plugins directory
+ ModuleFinder pluginsFinder = ModuleFinder.of(pluginsDir);
+
+ // Find all names of all found plugin modules
+ List<String> p = pluginsFinder
+ .findAll()
+ .stream()
+ .map(ModuleReference::descriptor)
+ .map(ModuleDescriptor::name)
+ .collect(Collectors.toList());
+
+ // Create configuration that will resolve plugin modules
+ // (verify that the graph of modules is correct)
+ Configuration pluginsConfiguration = ModuleLayer
+ .boot()
+ .configuration()
+ .resolve(pluginsFinder, ModuleFinder.of(), p);
+
+ // Create a module layer for plugins
+ ModuleLayer layer = ModuleLayer
+ .boot()
+ .defineModulesWithOneLoader(pluginsConfiguration, ClassLoader.getSystemClassLoader());
+
+ logger.info("Loading plugins from jar ...");
+ // Now you can use the new module layer to find service implementations in it
+ externalPlugins = ServiceLoader
+ .load(layer, NormalAction.class).stream()
+ .map(ServiceLoader.Provider::get)
+ .collect(Collectors.toList());
+
+ logger.info("...Done!");
+
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+
+ throw new MinorException("Error", "Error loading modules\n"+e.getMessage()+"\nPlease fix the errors. Other plugins wont be loaded.");
+ }
+
+
+ sortedPlugins = new HashMap<>();
+
+ for (ExternalPlugin eachPlugin : externalPlugins)
+ {
+ try
+ {
+ eachPlugin.setPropertySaver(propertySaver);
+ eachPlugin.setServerConnection(serverConnection);
+ eachPlugin.initProperties();
+
+ Action foundAction = null;
+ for (Action action : pluginsConfigs) {
+ if (action.getModuleName().equals(eachPlugin.getModuleName())
+ && action.getVersion().isEqual(eachPlugin.getVersion())) {
+
+ foundAction = action;
+
+ List<Property> eachPluginStoredProperties = action.getServerProperties().get();
+ List<Property> eachPluginCodeProperties = eachPlugin.getServerProperties().get();
+
+
+ for (int i =0;i< eachPluginCodeProperties.size(); i++) {
+
+ Property eachPluginCodeProperty = eachPluginCodeProperties.get(i);
+
+ Property foundProp = null;
+ for (Property eachPluginStoredProperty : eachPluginStoredProperties) {
+ if (eachPluginCodeProperty.getName().equals(eachPluginStoredProperty.getName())) {
+ eachPluginCodeProperty.setRawValue(eachPluginStoredProperty.getRawValue());
+ foundProp = eachPluginStoredProperty;
+ }
+ }
+
+ eachPluginCodeProperties.set(i, eachPluginCodeProperty);
+
+ if (foundProp != null) {
+ eachPluginStoredProperties.remove(foundProp);
+ }
+ }
+
+
+ eachPlugin.getServerProperties().set(eachPluginCodeProperties);
+
+ break;
+ }
+ }
+
+ if (foundAction != null)
+ pluginsConfigs.remove(foundAction);
+ else
+ {
+ List<Property> eachPluginStoredProperties = eachPlugin.getServerProperties().get();
+ for(Property property :eachPluginStoredProperties)
+ {
+ if(property.getType() == Type.STRING || property.getType() == Type.INTEGER || property.getType() == Type.DOUBLE)
+ property.setRawValue(property.getDefaultRawValue());
+ }
+ }
+
+
+
+ if (!sortedPlugins.containsKey(eachPlugin.getCategory())) {
+ ArrayList<ExternalPlugin> actions = new ArrayList<>();
+
+ sortedPlugins.put(eachPlugin.getCategory(), actions);
+ }
+
+ sortedPlugins.get(eachPlugin.getCategory()).add(eachPlugin);
+
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ errorModules.add(eachPlugin);
+ errorModuleError.add(e.getMessage());
+ }
+ }
+
+ try {
+ saveServerSettings();
+ } catch (MinorException e) {
+ e.printStackTrace();
+ }
+
+ logger.log(Level.INFO, "All plugins registered!");
+
+ if(errorModules.size() > 0)
+ {
+ StringBuilder errors = new StringBuilder("The following action modules could not be loaded:");
+ for(int i = 0; i<errorModules.size(); i++)
+ {
+ externalPlugins.remove(errorModules.get(i));
+ errors.append("\n * ").append(errorModules.get(i).getModuleName()).append("\n(")
+ .append(errorModuleError.get(i)).append(")");
+ }
+
+ throw new MinorException("Plugins", errors.toString());
+ }
+
+
+ for(int i = 0;i<externalPlugins.size();i++)
+ {
+ externalPluginsHashmap.put(externalPlugins.get(i).getModuleName(), i);
+ }
+ }
+
+ /**
+ * Used to init plugins
+ */
+ public void initPlugins() throws MinorException
+ {
+ StringBuilder errors = new StringBuilder("There were errors registering the following plugins. As a result, they have been omitted : ");
+ boolean isError = false;
+
+ for(ExternalPlugin eachPlugin : externalPlugins)
+ {
+ try
+ {
+ eachPlugin.initAction();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ isError = true;
+ errors.append("\n* ")
+ .append(eachPlugin.getName())
+ .append(" - ")
+ .append(eachPlugin.getModuleName())
+ .append("\n");
+
+ if(e instanceof StreamPiException)
+ errors.append(((MinorException) e).getShortMessage());
+
+ errors.append("\n");
+ }
+ }
+
+ if(isError)
+ {
+ throw new MinorException("Plugin init error", errors.toString());
+ }
+ }
+
+ HashMap<String, ArrayList<ExternalPlugin>> sortedPlugins;
+
+ /**
+ * Gets list of sorted plugins
+ *
+ * @return Hashmap with category key, and list of plugins of each category
+ */
+ public HashMap<String, ArrayList<ExternalPlugin>> getSortedPlugins()
+ {
+ return sortedPlugins;
+ }
+
+ /**
+ * @return Gets actions element from the config.xml in plugins folder
+ */
+ private Element getActionsElement()
+ {
+ return (Element) document.getElementsByTagName("actions").item(0);
+ }
+
+ /**
+ * Saves ServerProperties of every plugin in config.xml in plugins folder
+ *
+ * @throws MinorException Thrown when failed to save settings
+ */
+ public void saveServerSettings() throws MinorException
+ {
+ XMLConfigHelper.removeChilds(getActionsElement());
+
+ for(ExternalPlugin normalAction : externalPlugins)
+ {
+ Element actionElement = document.createElement("action");
+ getActionsElement().appendChild(actionElement);
+
+ Element moduleNameElement = document.createElement("module-name");
+ moduleNameElement.setTextContent(normalAction.getModuleName());
+ actionElement.appendChild(moduleNameElement);
+
+
+ Element versionElement = document.createElement("version");
+ versionElement.setTextContent(normalAction.getVersion().getText());
+ actionElement.appendChild(versionElement);
+
+ Element propertiesElement = document.createElement("properties");
+ actionElement.appendChild(propertiesElement);
+
+ for(String key : normalAction.getServerProperties().getNames())
+ {
+ for(Property eachProperty : normalAction.getServerProperties().getMultipleProperties(key))
+ {
+ Element propertyElement = document.createElement("property");
+ propertiesElement.appendChild(propertyElement);
+
+ Element nameElement = document.createElement("name");
+ nameElement.setTextContent(eachProperty.getName());
+ propertyElement.appendChild(nameElement);
+
+ Element valueElement = document.createElement("value");
+ valueElement.setTextContent(eachProperty.getRawValue());
+ propertyElement.appendChild(valueElement);
+ }
+ }
+ }
+
+ save();
+ }
+
+ private PropertySaver propertySaver = null;
+
+ /**
+ * Set PropertySaver class
+ * @param propertySaver instance of PropertySaver
+ */
+ public void setPropertySaver(PropertySaver propertySaver)
+ {
+ this.propertySaver = propertySaver;
+ }
+
+ private ServerConnection serverConnection = null;
+
+ /**
+ * Set setServerConnection class
+ * @param serverConnection instance of ServerConnection
+ */
+ public void setServerConnection(ServerConnection serverConnection)
+ {
+ this.serverConnection = serverConnection;
+ }
+
+ /**
+ * Get plugin from index from list
+ *
+ * @param index of plugin
+ * @return found plugin
+ */
+ public ExternalPlugin getActionFromIndex(int index)
+ {
+ return externalPlugins.get(index);
+ }
+
+ /**
+ * Calls onShutDown method in every plugin
+ */
+ public void shutDownActions()
+ {
+ if(externalPlugins != null)
+ {
+ for(ExternalPlugin eachPlugin : externalPlugins)
+ {
+ try
+ {
+ eachPlugin.onShutDown();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ externalPlugins.clear();
+ }
+ }
+
+ /**
+ * Saves all Server Properties of each Plugin in config.xml in Plugins folder
+ * @throws MinorException thrown when failed to save
+ */
+ public void save() throws MinorException
+ {
+ try
+ {
+ Transformer transformer = TransformerFactory.newInstance().newTransformer();
+ Result output = new StreamResult(configFile);
+ Source input = new DOMSource(document);
+
+ transformer.transform(input, output);
+ }
+ catch (Exception e)
+ {
+ throw new MinorException("Config", "unable to save server plugins settings");
+ }
+ }
+}
--- 'a/src/main/java/com/stream_pi/server/action/NormalActionPlugins.java'
+++ /dev/null
@@ -1,571 +0,0 @@
-/*
-Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macropad
-Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones)
-
-This program is free software: you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation, either version 3 of the License, or
-(at your option) any later version.
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-Written by : Debayan Sutradhar (rnayabed)
-*/
-
-package com.stream_pi.server.action;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.transform.Result;
-import javax.xml.transform.Source;
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.transform.stream.StreamResult;
-
-import com.stream_pi.action_api.action.Action;
-import com.stream_pi.action_api.action.ActionType;
-import com.stream_pi.action_api.action.PropertySaver;
-import com.stream_pi.action_api.action.ServerConnection;
-import com.stream_pi.action_api.actionproperty.ServerProperties;
-import com.stream_pi.action_api.actionproperty.property.Property;
-import com.stream_pi.action_api.actionproperty.property.Type;
-import com.stream_pi.action_api.normalaction.NormalAction;
-import com.stream_pi.util.exception.MinorException;
-import com.stream_pi.util.exception.SevereException;
-import com.stream_pi.util.exception.StreamPiException;
-import com.stream_pi.util.version.Version;
-import com.stream_pi.util.xmlconfighelper.XMLConfigHelper;
-import org.w3c.dom.NodeList;
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-
-import java.io.File;
-import java.lang.module.*;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.ServiceLoader;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.stream.Collectors;
-
-import org.w3c.dom.Element;
-
-public class NormalActionPlugins
-{
- private static NormalActionPlugins instance = null;
- private final Logger logger;
-
- private File configFile;
- private Document document;
-
- private static String pluginsLocation = null;
-
-
- /**
- * Singleton class instance getter. Creates new one, when asked for the first time
- *
- * @return returns instance of NormalActionPlugins (one and only, always)
- */
- public static synchronized NormalActionPlugins getInstance()
- {
- if(instance == null)
- {
- instance = new NormalActionPlugins();
- }
-
- return instance;
- }
-
- /**
- * Sets the folder location where the plugin JARs and their dependencies are stored
- *
- * @param location Folder location
- */
- public static void setPluginsLocation(String location)
- {
- pluginsLocation = location;
- }
-
- /**
- * Private constructor
- */
- private NormalActionPlugins()
- {
- logger = Logger.getLogger(NormalActionPlugins.class.getName());
- normalPluginsHashmap = new HashMap<>();
- }
-
- /**
- * init Method
- */
- public void init() throws SevereException, MinorException
- {
- registerPlugins();
- initPlugins();
- }
-
- /**
- * Used to fetch list of all external Plugins
- *
- * @return List of plugins
- */
- public List<NormalAction> getPlugins()
- {
- return normalPlugins;
- }
-
- /**
- * Returns a plugin by its module name
- *
- * @param name Module Name
- * @return The plugin. If not found, then null is returned
- */
- public NormalAction getPluginByModuleName(String name)
- {
- logger.info("Plugin being requested : "+name);
- Integer index = normalPluginsHashmap.getOrDefault(name, -1);
- if(index != -1)
- {
- return normalPlugins.get(index);
- }
-
- return null;
- }
-
- private List<NormalAction> normalPlugins = null;
- HashMap<String, Integer> normalPluginsHashmap;
-
- /**
- * Used to register plugins from plugin location
- */
- public void registerPlugins() throws SevereException, MinorException
- {
- logger.info("Registering external plugins from "+pluginsLocation+" ...");
-
- try
- {
- configFile = new File(pluginsLocation+"/config.xml");
- DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
- DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
- document = docBuilder.parse(configFile);
- }
- catch (Exception e)
- {
- e.printStackTrace();
- throw new SevereException("Plugins","Error reading plugins config.xml. Cannot continue.");
- }
-
- ArrayList<NormalAction> errorModules = new ArrayList<>();
- ArrayList<String> errorModuleError = new ArrayList<>();
-
- ArrayList<Action> pluginsConfigs = new ArrayList<>();
-
- NodeList actionsNode = document.getElementsByTagName("actions").item(0).getChildNodes();
-
- for(int i =0;i<actionsNode.getLength();i++)
- {
- Node eachActionNode = actionsNode.item(i);
-
- if(eachActionNode.getNodeType() != Node.ELEMENT_NODE)
- continue;
-
- if(!eachActionNode.getNodeName().equals("action"))
- continue;
-
- Element eachActionElement = (Element) eachActionNode;
-
-
-
- String name;
- Version version;
- try
- {
- name = XMLConfigHelper.getStringProperty(eachActionElement, "module-name");
- version = new Version(XMLConfigHelper.getStringProperty(eachActionElement, "version"));
- }
- catch (Exception e)
- {
- logger.log(Level.WARNING, "Skipping configuration because invalid ...");
- e.printStackTrace();
- continue;
- }
-
- ServerProperties serverProperties = new ServerProperties();
-
- NodeList serverPropertiesNodeList = eachActionElement.getElementsByTagName("properties").item(0).getChildNodes();
-
- for(int j = 0;j<serverPropertiesNodeList.getLength();j++)
- {
- Node eachPropertyNode = serverPropertiesNodeList.item(j);
-
-
- if(eachPropertyNode.getNodeType() != Node.ELEMENT_NODE)
- continue;
-
- if(!eachPropertyNode.getNodeName().equals("property"))
- continue;
-
-
- Element eachPropertyElement = (Element) eachPropertyNode;
-
- try
- {
- Property property = new Property(XMLConfigHelper.getStringProperty(eachPropertyElement, "name"), Type.STRING);
- property.setRawValue(XMLConfigHelper.getStringProperty(eachPropertyElement, "value"));
-
- serverProperties.addProperty(property);
- }
- catch (Exception e)
- {
- logger.log(Level.WARNING, "Skipping property because invalid ...");
- e.printStackTrace();
- }
- }
-
- Action action = new Action(ActionType.NORMAL);
-
- action.setModuleName(name);
- action.setVersion(version);
- action.getServerProperties().set(serverProperties);
-
- pluginsConfigs.add(action);
- }
-
- logger.info("Size : "+pluginsConfigs.size());
-
- Path pluginsDir = Paths.get(pluginsLocation); // Directory with plugins JARs
- try
- {
- // Search for plugins in the plugins directory
- ModuleFinder pluginsFinder = ModuleFinder.of(pluginsDir);
-
- // Find all names of all found plugin modules
- List<String> p = pluginsFinder
- .findAll()
- .stream()
- .map(ModuleReference::descriptor)
- .map(ModuleDescriptor::name)
- .collect(Collectors.toList());
-
- // Create configuration that will resolve plugin modules
- // (verify that the graph of modules is correct)
- Configuration pluginsConfiguration = ModuleLayer
- .boot()
- .configuration()
- .resolve(pluginsFinder, ModuleFinder.of(), p);
-
- // Create a module layer for plugins
- ModuleLayer layer = ModuleLayer
- .boot()
- .defineModulesWithOneLoader(pluginsConfiguration, ClassLoader.getSystemClassLoader());
-
- logger.info("Loading plugins from jar ...");
- // Now you can use the new module layer to find service implementations in it
- normalPlugins = ServiceLoader
- .load(layer, NormalAction.class).stream()
- .map(ServiceLoader.Provider::get)
- .collect(Collectors.toList());
-
- logger.info("...Done!");
-
- }
- catch (Exception e)
- {
- e.printStackTrace();
-
- throw new MinorException("Error", "Error loading modules\n"+e.getMessage()+"\nPlease fix the errors. Other plugins wont be loaded.");
- }
-
-
- sortedPlugins = new HashMap<>();
-
- for (NormalAction eachPlugin : normalPlugins)
- {
- try
- {
- eachPlugin.setPropertySaver(propertySaver);
- eachPlugin.setServerConnection(serverConnection);
- eachPlugin.initProperties();
-
- Action foundAction = null;
- for (Action action : pluginsConfigs) {
- if (action.getModuleName().equals(eachPlugin.getModuleName())
- && action.getVersion().isEqual(eachPlugin.getVersion())) {
-
- foundAction = action;
-
- List<Property> eachPluginStoredProperties = action.getServerProperties().get();
- List<Property> eachPluginCodeProperties = eachPlugin.getServerProperties().get();
-
-
- for (int i =0;i< eachPluginCodeProperties.size(); i++) {
-
- Property eachPluginCodeProperty = eachPluginCodeProperties.get(i);
-
- Property foundProp = null;
- for (Property eachPluginStoredProperty : eachPluginStoredProperties) {
- if (eachPluginCodeProperty.getName().equals(eachPluginStoredProperty.getName())) {
- eachPluginCodeProperty.setRawValue(eachPluginStoredProperty.getRawValue());
- foundProp = eachPluginStoredProperty;
- }
- }
-
- eachPluginCodeProperties.set(i, eachPluginCodeProperty);
-
- if (foundProp != null) {
- eachPluginStoredProperties.remove(foundProp);
- }
- }
-
-
- eachPlugin.getServerProperties().set(eachPluginCodeProperties);
-
- break;
- }
- }
-
- if (foundAction != null)
- pluginsConfigs.remove(foundAction);
- else
- {
- List<Property> eachPluginStoredProperties = eachPlugin.getServerProperties().get();
- for(Property property :eachPluginStoredProperties)
- {
- if(property.getType() == Type.STRING || property.getType() == Type.INTEGER || property.getType() == Type.DOUBLE)
- property.setRawValue(property.getDefaultRawValue());
- }
- }
-
-
-
- if (!sortedPlugins.containsKey(eachPlugin.getCategory())) {
- ArrayList<NormalAction> actions = new ArrayList<>();
-
- sortedPlugins.put(eachPlugin.getCategory(), actions);
- }
-
- sortedPlugins.get(eachPlugin.getCategory()).add(eachPlugin);
-
- }
- catch (Exception e)
- {
- e.printStackTrace();
- errorModules.add(eachPlugin);
- errorModuleError.add(e.getMessage());
- }
- }
-
- try {
- saveServerSettings();
- } catch (MinorException e) {
- e.printStackTrace();
- }
-
- logger.log(Level.INFO, "All plugins registered!");
-
- if(errorModules.size() > 0)
- {
- StringBuilder errors = new StringBuilder("The following action modules could not be loaded:");
- for(int i = 0; i<errorModules.size(); i++)
- {
- normalPlugins.remove(errorModules.get(i));
- errors.append("\n * ").append(errorModules.get(i).getModuleName()).append("\n(")
- .append(errorModuleError.get(i)).append(")");
- }
-
- throw new MinorException("Plugins", errors.toString());
- }
-
-
- for(int i = 0;i<normalPlugins.size();i++)
- {
- normalPluginsHashmap.put(normalPlugins.get(i).getModuleName(), i);
- }
- }
-
- /**
- * Used to init plugins
- */
- public void initPlugins() throws MinorException
- {
- StringBuilder errors = new StringBuilder("There were errors registering the following plugins. As a result, they have been omitted : ");
- boolean isError = false;
-
- for(NormalAction eachPlugin : normalPlugins)
- {
- try
- {
- eachPlugin.initAction();
- }
- catch (Exception e)
- {
- e.printStackTrace();
- isError = true;
- errors.append("\n* ")
- .append(eachPlugin.getName())
- .append(" - ")
- .append(eachPlugin.getModuleName())
- .append("\n");
-
- if(e instanceof StreamPiException)
- errors.append(((MinorException) e).getShortMessage());
-
- errors.append("\n");
- }
- }
-
- if(isError)
- {
- throw new MinorException("Plugin init error", errors.toString());
- }
- }
-
- HashMap<String, ArrayList<NormalAction>> sortedPlugins;
-
- /**
- * Gets list of sorted plugins
- *
- * @return Hashmap with category key, and list of plugins of each category
- */
- public HashMap<String, ArrayList<NormalAction>> getSortedPlugins()
- {
- return sortedPlugins;
- }
-
- /**
- * @return Gets actions element from the config.xml in plugins folder
- */
- private Element getActionsElement()
- {
- return (Element) document.getElementsByTagName("actions").item(0);
- }
-
- /**
- * Saves ServerProperties of every plugin in config.xml in plugins folder
- *
- * @throws MinorException Thrown when failed to save settings
- */
- public void saveServerSettings() throws MinorException
- {
- XMLConfigHelper.removeChilds(getActionsElement());
-
- for(NormalAction normalAction : normalPlugins)
- {
- Element actionElement = document.createElement("action");
- getActionsElement().appendChild(actionElement);
-
- Element moduleNameElement = document.createElement("module-name");
- moduleNameElement.setTextContent(normalAction.getModuleName());
- actionElement.appendChild(moduleNameElement);
-
-
- Element versionElement = document.createElement("version");
- versionElement.setTextContent(normalAction.getVersion().getText());
- actionElement.appendChild(versionElement);
-
- Element propertiesElement = document.createElement("properties");
- actionElement.appendChild(propertiesElement);
-
- for(String key : normalAction.getServerProperties().getNames())
- {
- for(Property eachProperty : normalAction.getServerProperties().getMultipleProperties(key))
- {
- Element propertyElement = document.createElement("property");
- propertiesElement.appendChild(propertyElement);
-
- Element nameElement = document.createElement("name");
- nameElement.setTextContent(eachProperty.getName());
- propertyElement.appendChild(nameElement);
-
- Element valueElement = document.createElement("value");
- valueElement.setTextContent(eachProperty.getRawValue());
- propertyElement.appendChild(valueElement);
- }
- }
- }
-
- save();
- }
-
- private PropertySaver propertySaver = null;
-
- /**
- * Set PropertySaver class
- * @param propertySaver instance of PropertySaver
- */
- public void setPropertySaver(PropertySaver propertySaver)
- {
- this.propertySaver = propertySaver;
- }
-
- private ServerConnection serverConnection = null;
-
- /**
- * Set setServerConnection class
- * @param serverConnection instance of ServerConnection
- */
- public void setServerConnection(ServerConnection serverConnection)
- {
- this.serverConnection = serverConnection;
- }
-
- /**
- * Get plugin from index from list
- *
- * @param index of plugin
- * @return found plugin
- */
- public NormalAction getActionFromIndex(int index)
- {
- return normalPlugins.get(index);
- }
-
- /**
- * Calls onShutDown method in every plugin
- */
- public void shutDownActions()
- {
- if(normalPlugins != null)
- {
- for(NormalAction eachPlugin : normalPlugins)
- {
- try
- {
- eachPlugin.onShutDown();
- }
- catch (Exception e)
- {
- e.printStackTrace();
- }
- }
-
- normalPlugins.clear();
- }
- }
-
- /**
- * Saves all Server Properties of each Plugin in config.xml in Plugins folder
- * @throws MinorException thrown when failed to save
- */
- public void save() throws MinorException
- {
- try
- {
- Transformer transformer = TransformerFactory.newInstance().newTransformer();
- Result output = new StreamResult(configFile);
- Source input = new DOMSource(document);
-
- transformer.transform(input, output);
- }
- catch (Exception e)
- {
- throw new MinorException("Config", "unable to save server plugins settings");
- }
- }
-}
--- 'a/src/main/java/com/stream_pi/server/connection/ClientConnection.java'
+++ b/src/main/java/com/stream_pi/server/connection/ClientConnection.java
@@ -7,9 +7,10 @@ import com.stream_pi.action_api.action.L
import com.stream_pi.action_api.actionproperty.ClientProperties;
import com.stream_pi.action_api.actionproperty.property.Property;
import com.stream_pi.action_api.actionproperty.property.Type;
+import com.stream_pi.action_api.normalaction.ExternalPlugin;
import com.stream_pi.action_api.normalaction.NormalAction;
import com.stream_pi.action_api.normalaction.ToggleAction;
-import com.stream_pi.server.action.NormalActionPlugins;
+import com.stream_pi.server.action.ExternalPlugins;
import com.stream_pi.server.client.Client;
import com.stream_pi.server.client.ClientProfile;
import com.stream_pi.server.client.ClientTheme;
@@ -27,7 +28,6 @@ import com.stream_pi.util.version.Versio
import javafx.concurrent.Task;
import java.io.*;
-import java.lang.reflect.Array;
import java.net.Socket;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -505,7 +505,7 @@ public class ClientConnection extends Th
if(actionType == ActionType.NORMAL)
{
- NormalAction actionCopy = NormalActionPlugins.getInstance().getPluginByModuleName(r[4]);
+ ExternalPlugin actionCopy = ExternalPlugins.getInstance().getPluginByModuleName(r[4]);
if(actionCopy == null)
{
@@ -722,7 +722,7 @@ public class ClientConnection extends Th
if(action.getActionType() == ActionType.NORMAL || action.getActionType() == ActionType.TOGGLE)
{
- NormalAction original = NormalActionPlugins.getInstance().getPluginByModuleName(
+ ExternalPlugin original = ExternalPlugins.getInstance().getPluginByModuleName(
action.getModuleName()
);
@@ -733,16 +733,18 @@ public class ClientConnection extends Th
);
}
- NormalAction normalAction = original.clone();
+ ExternalPlugin externalPlugin = original.clone();
- normalAction.setLocation(action.getLocation());
- normalAction.setDisplayText(action.getDisplayText());
- normalAction.setID(actionID);
- normalAction.setDelayBeforeExecuting(action.getDelayBeforeExecuting());
+ externalPlugin.setLocation(action.getLocation());
+ externalPlugin.setDisplayText(action.getDisplayText());
+ externalPlugin.setID(actionID);
+ externalPlugin.setDelayBeforeExecuting(action.getDelayBeforeExecuting());
+
+ externalPlugin.setClientProperties(action.getClientProperties());
+
- normalAction.setClientProperties(action.getClientProperties());
new Thread(new Task<Void>() {
@Override
@@ -750,12 +752,12 @@ public class ClientConnection extends Th
{
try
{
- System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@2 "+normalAction.getDelayBeforeExecuting());
- Thread.sleep(normalAction.getDelayBeforeExecuting());
+ System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@2 "+externalPlugin.getDelayBeforeExecuting());
+ Thread.sleep(externalPlugin.getDelayBeforeExecuting());
- if(normalAction instanceof ToggleAction)
+ if(externalPlugin instanceof ToggleAction)
{
- boolean result = serverListener.onToggleActionClicked((ToggleAction) normalAction, toggle);
+ boolean result = serverListener.onToggleActionClicked((ToggleAction) externalPlugin, toggle);
if(!result)
{
sendActionFailed(profileID, actionID);
@@ -763,7 +765,7 @@ public class ClientConnection extends Th
}
else
{
- boolean result = serverListener.onNormalActionClicked(normalAction);
+ boolean result = serverListener.onNormalActionClicked((NormalAction) externalPlugin);
if(!result)
{
sendActionFailed(profileID, actionID);
--- 'a/src/main/java/com/stream_pi/server/controller/Controller.java'
+++ b/src/main/java/com/stream_pi/server/controller/Controller.java
@@ -5,7 +5,7 @@ import com.stream_pi.action_api.action.P
import com.stream_pi.action_api.normalaction.NormalAction;
import com.stream_pi.action_api.normalaction.ToggleAction;
import com.stream_pi.server.Main;
-import com.stream_pi.server.action.NormalActionPlugins;
+import com.stream_pi.server.action.ExternalPlugins;
import com.stream_pi.server.connection.ClientConnections;
import com.stream_pi.server.connection.MainServer;
import com.stream_pi.server.io.Config;
@@ -18,7 +18,6 @@ import com.stream_pi.util.alert.StreamPi
import com.stream_pi.util.alert.StreamPiAlertType;
import com.stream_pi.util.exception.MinorException;
import com.stream_pi.util.exception.SevereException;
-import com.stream_pi.util.iohelper.IOHelper;
import javafx.animation.Interpolator;
import javafx.animation.KeyFrame;
@@ -26,7 +25,6 @@ import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.concurrent.Task;
-import javafx.event.EventHandler;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.stage.Modality;
@@ -39,11 +37,9 @@ import java.awt.TrayIcon;
import java.awt.PopupMenu;
import java.awt.MenuItem;
-import java.io.File;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
-import java.net.UnknownHostException;
import java.util.Enumeration;
import java.util.Random;
import java.util.logging.Level;
@@ -98,8 +94,8 @@ public class Controller extends Base imp
setupSettingsWindowsAnimations();
- NormalActionPlugins.getInstance().setPropertySaver(this);
- NormalActionPlugins.getInstance().setServerConnection(this);
+ ExternalPlugins.getInstance().setPropertySaver(this);
+ ExternalPlugins.getInstance().setServerConnection(this);
getDashboardPane().getPluginsPane().getSettingsButton().setOnAction(event -> {
@@ -186,8 +182,8 @@ public class Controller extends Base imp
getDashboardPane().getPluginsPane().loadOtherActions();
});
- NormalActionPlugins.setPluginsLocation(getConfig().getPluginsPath());
- NormalActionPlugins.getInstance().init();
+ ExternalPlugins.setPluginsLocation(getConfig().getPluginsPath());
+ ExternalPlugins.getInstance().init();
Platform.runLater(()->getDashboardPane().getPluginsPane().loadData());
@@ -370,7 +366,7 @@ public class Controller extends Base imp
);
getConfig().save();
onQuitApp();
- NormalActionPlugins.getInstance().shutDownActions();
+ ExternalPlugins.getInstance().shutDownActions();
Platform.exit();
}
catch (SevereException e)
@@ -572,7 +568,7 @@ public class Controller extends Base imp
{
try
{
- NormalActionPlugins.getInstance().saveServerSettings();
+ ExternalPlugins.getInstance().saveServerSettings();
getSettingsPane().getPluginsSettings().loadPlugins();
} catch (MinorException e) {
e.printStackTrace();
--- 'a/src/main/java/com/stream_pi/server/window/dashboard/PluginsPane.java'
+++ b/src/main/java/com/stream_pi/server/window/dashboard/PluginsPane.java
@@ -4,10 +4,11 @@ import com.stream_pi.action_api.action.A
import com.stream_pi.action_api.action.DisplayTextAlignment;
import com.stream_pi.action_api.actionproperty.property.Property;
import com.stream_pi.action_api.actionproperty.property.Type;
+import com.stream_pi.action_api.normalaction.ExternalPlugin;
import com.stream_pi.action_api.normalaction.NormalAction;
import com.stream_pi.action_api.otheractions.CombineAction;
import com.stream_pi.action_api.otheractions.FolderAction;
-import com.stream_pi.server.action.NormalActionPlugins;
+import com.stream_pi.server.action.ExternalPlugins;
import com.stream_pi.util.uihelper.SpaceFiller;
import javafx.application.HostServices;
@@ -78,7 +79,7 @@ public class PluginsPane extends VBox {
public void loadData()
{
- HashMap<String, ArrayList<NormalAction>> sortedPlugins = NormalActionPlugins.getInstance().getSortedPlugins();
+ HashMap<String, ArrayList<ExternalPlugin>> sortedPlugins = ExternalPlugins.getInstance().getSortedPlugins();
for(String eachCategory : sortedPlugins.keySet())
{
@@ -87,7 +88,7 @@ public class PluginsPane extends VBox {
TitledPane pane = new TitledPane(eachCategory, vBox);
pane.getStyleClass().add("plugins_pane_each_plugin_category_titled_pane");
- for(NormalAction eachAction : sortedPlugins.get(eachCategory))
+ for(ExternalPlugin eachAction : sortedPlugins.get(eachCategory))
{
if(!eachAction.isVisibleInPluginsPane())
continue;
@@ -195,8 +196,6 @@ public class PluginsPane extends VBox {
newAction.setShowDisplayText(true);
newAction.setDisplayText(displayText);
newAction.setDisplayTextAlignment(DisplayTextAlignment.CENTER);
- newAction.setShowIcon(false);
- newAction.setHasIcon(false);
//action.setParent(root);
--- 'a/src/main/java/com/stream_pi/server/window/settings/PluginsSettings.java'
+++ b/src/main/java/com/stream_pi/server/window/settings/PluginsSettings.java
@@ -1,11 +1,12 @@
package com.stream_pi.server.window.settings;
+import com.stream_pi.action_api.normalaction.ExternalPlugin;
import com.stream_pi.server.uipropertybox.UIPropertyBox;
import com.stream_pi.action_api.actionproperty.property.ControlType;
import com.stream_pi.action_api.actionproperty.property.Property;
import com.stream_pi.action_api.actionproperty.property.Type;
import com.stream_pi.action_api.normalaction.NormalAction;
-import com.stream_pi.server.action.NormalActionPlugins;
+import com.stream_pi.server.action.ExternalPlugins;
import com.stream_pi.server.connection.ServerListener;
import com.stream_pi.server.window.ExceptionAndAlertHandler;
import com.stream_pi.util.exception.MinorException;
@@ -15,7 +16,6 @@ import org.kordamp.ikonli.javafx.FontIco
import javafx.application.HostServices;
import javafx.application.Platform;
-import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Node;
import javafx.scene.control.*;
@@ -144,16 +144,16 @@ public class PluginsSettings extends VBo
String rawValue = serverProperty.getRawValue();
- NormalActionPlugins.getInstance().getActionFromIndex(pp.getIndex())
+ ExternalPlugins.getInstance().getActionFromIndex(pp.getIndex())
.getServerProperties().get()
.get(serverProperty.getIndex()).setRawValue(rawValue);
}
}
- NormalActionPlugins.getInstance().saveServerSettings();
+ ExternalPlugins.getInstance().saveServerSettings();
- NormalActionPlugins.getInstance().initPlugins();
+ ExternalPlugins.getInstance().initPlugins();
}
catch (MinorException e)
{
@@ -177,7 +177,7 @@ public class PluginsSettings extends VBo
pluginProperties.clear();
- List<NormalAction> actions = NormalActionPlugins.getInstance().getPlugins();
+ List<ExternalPlugin> actions = ExternalPlugins.getInstance().getPlugins();
Platform.runLater(()-> pluginsSettingsVBox.getChildren().clear());
@@ -199,7 +199,7 @@ public class PluginsSettings extends VBo
for(int i = 0; i<actions.size(); i++)
{
- NormalAction action = actions.get(i);
+ ExternalPlugin action = actions.get(i);
if(!action.isVisibleInServerSettingsPane())
continue;