server
Clone or download
Modified Files
/*
/*
Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macropad
Stream-Pi - Free & Open-Source Modular Cross-Platform Programmable Macropad
Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones)
Copyright (C) 2019-2021 Debayan Sutradhar (rnayabed), Samuel Quiñones (SamuelQuinones)
This program is free software: you can redistribute it and/or modify
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
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
(at your option) any later version.
This program is distributed in the hope that it will be useful,
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
GNU General Public License for more details.
Written by : Debayan Sutradhar (rnayabed)
Written by : Debayan Sutradhar (rnayabed)
*/
*/
package com.stream_pi.server.action;
package com.stream_pi.server.action;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Result;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamResult;
import com.stream_pi.action_api.action.Action;
import com.stream_pi.action_api.action.Action;
import com.stream_pi.action_api.action.ActionType;
import com.stream_pi.action_api.action.ActionType;
import com.stream_pi.action_api.action.PropertySaver;
import com.stream_pi.action_api.action.PropertySaver;
import com.stream_pi.action_api.action.ServerConnection;
import com.stream_pi.action_api.action.ServerConnection;
import com.stream_pi.action_api.actionproperty.ServerProperties;
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.Property;
import com.stream_pi.action_api.actionproperty.property.Type;
import com.stream_pi.action_api.actionproperty.property.Type;
import com.stream_pi.action_api.normalaction.ExternalPlugin;
import com.stream_pi.action_api.normalaction.ExternalPlugin;
import com.stream_pi.action_api.normalaction.NormalAction;
import com.stream_pi.action_api.normalaction.NormalAction;
import com.stream_pi.util.exception.MinorException;
import com.stream_pi.util.exception.MinorException;
import com.stream_pi.util.exception.SevereException;
import com.stream_pi.util.exception.SevereException;
import com.stream_pi.util.exception.StreamPiException;
import com.stream_pi.util.exception.StreamPiException;
import com.stream_pi.util.version.Version;
import com.stream_pi.util.version.Version;
import com.stream_pi.util.xmlconfighelper.XMLConfigHelper;
import com.stream_pi.util.xmlconfighelper.XMLConfigHelper;
import org.w3c.dom.NodeList;
import org.w3c.dom.NodeList;
import org.w3c.dom.Document;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.Node;
import java.io.File;
import java.io.File;
import java.lang.module.*;
import java.lang.module.*;
import java.nio.file.Path;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashMap;
import java.util.List;
import java.util.List;
import java.util.ServiceLoader;
import java.util.ServiceLoader;
import java.util.logging.Level;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Collectors;
import org.w3c.dom.Element;
import org.w3c.dom.Element;
public class ExternalPlugins
public class ExternalPlugins
{
{
private static ExternalPlugins instance = null;
private static ExternalPlugins instance = null;
private final Logger logger;
private final Logger logger;
private File configFile;
private File configFile;
private Document document;
private Document document;
private static String pluginsLocation = null;
private static String pluginsLocation = null;
/**
/**
* Singleton class instance getter. Creates new one, when asked for the first time
* Singleton class instance getter. Creates new one, when asked for the first time
*
*
* @return returns instance of NormalActionPlugins (one and only, always)
* @return returns instance of NormalActionPlugins (one and only, always)
*/
*/
public static synchronized ExternalPlugins getInstance()
public static synchronized ExternalPlugins getInstance()
{
{
if(instance == null)
if(instance == null)
{
{
instance = new ExternalPlugins();
instance = new ExternalPlugins();
}
}
return instance;
return instance;
}
}
/**
/**
* Sets the folder location where the plugin JARs and their dependencies are stored
* Sets the folder location where the plugin JARs and their dependencies are stored
*
*
* @param location Folder location
* @param location Folder location
*/
*/
public static void setPluginsLocation(String location)
public static void setPluginsLocation(String location)
{
{
pluginsLocation = location;
pluginsLocation = location;
}
}
/**
/**
* Private constructor
* Private constructor
*/
*/
private ExternalPlugins()
private ExternalPlugins()
{
{
logger = Logger.getLogger(ExternalPlugins.class.getName());
logger = Logger.getLogger(ExternalPlugins.class.getName());
externalPluginsHashmap = new HashMap<>();
externalPluginsHashmap = new HashMap<>();
}
}
/**
/**
* init Method
* init Method
*/
*/
public void init() throws SevereException, MinorException
public void init() throws SevereException, MinorException
{
{
registerPlugins();
registerPlugins();
initPlugins();
initPlugins();
}
}
/**
/**
* Used to fetch list of all external Plugins
* Used to fetch list of all external Plugins
*
*
* @return List of plugins
* @return List of plugins
*/
*/
public List<ExternalPlugin> getPlugins()
public List<ExternalPlugin> getPlugins()
{
{
return externalPlugins;
return externalPlugins;
}
}
/**
/**
* Returns a plugin by its module name
* Returns a plugin by its module name
*
*
* @param name Module Name
* @param name Module Name
* @return The plugin. If not found, then null is returned
* @return The plugin. If not found, then null is returned
*/
*/
public ExternalPlugin getPluginByModuleName(String name)
public ExternalPlugin getPluginByModuleName(String name)
{
{
logger.info("Plugin being requested : "+name);
logger.info("Plugin being requested : "+name);
Integer index = externalPluginsHashmap.getOrDefault(name, -1);
Integer index = externalPluginsHashmap.getOrDefault(name, -1);
if(index != -1)
if(index != -1)
{
{
return externalPlugins.get(index);
return externalPlugins.get(index);
}
}
return null;
return null;
}
}
private List<ExternalPlugin> externalPlugins = null;
private List<ExternalPlugin> externalPlugins = null;
HashMap<String, Integer> externalPluginsHashmap;
HashMap<String, Integer> externalPluginsHashmap;
/**
/**
* Used to register plugins from plugin location
* Used to register plugins from plugin location
*/
*/
public void registerPlugins() throws SevereException, MinorException
public void registerPlugins() throws SevereException, MinorException
{
{
logger.info("Registering external plugins from "+pluginsLocation+" ...");
logger.info("Registering external plugins from "+pluginsLocation+" ...");
try
try
{
{
configFile = new File(pluginsLocation+"/config.xml");
configFile = new File(pluginsLocation+"/config.xml");
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
document = docBuilder.parse(configFile);
document = docBuilder.parse(configFile);
}
}
catch (Exception e)
catch (Exception e)
{
{
e.printStackTrace();
e.printStackTrace();
throw new SevereException("Plugins","Error reading plugins config.xml. Cannot continue.");
throw new SevereException("Plugins","Error reading plugins config.xml. Cannot continue.");
}
}
ArrayList<ExternalPlugin> errorModules = new ArrayList<>();
ArrayList<ExternalPlugin> errorModules = new ArrayList<>();
ArrayList<String> errorModuleError = new ArrayList<>();
ArrayList<String> errorModuleError = new ArrayList<>();
ArrayList<Action> pluginsConfigs = new ArrayList<>();
ArrayList<Action> pluginsConfigs = new ArrayList<>();
NodeList actionsNode = document.getElementsByTagName("actions").item(0).getChildNodes();
NodeList actionsNode = document.getElementsByTagName("actions").item(0).getChildNodes();
for(int i =0;i<actionsNode.getLength();i++)
for(int i =0;i<actionsNode.getLength();i++)
{
{
Node eachActionNode = actionsNode.item(i);
Node eachActionNode = actionsNode.item(i);
if(eachActionNode.getNodeType() != Node.ELEMENT_NODE)
if(eachActionNode.getNodeType() != Node.ELEMENT_NODE)
continue;
continue;
if(!eachActionNode.getNodeName().equals("action"))
if(!eachActionNode.getNodeName().equals("action"))
continue;
continue;
Element eachActionElement = (Element) eachActionNode;
Element eachActionElement = (Element) eachActionNode;
String name;
String name;
Version version;
Version version;
try
try
{
{
name = XMLConfigHelper.getStringProperty(eachActionElement, "module-name");
name = XMLConfigHelper.getStringProperty(eachActionElement, "module-name");
version = new Version(XMLConfigHelper.getStringProperty(eachActionElement, "version"));
version = new Version(XMLConfigHelper.getStringProperty(eachActionElement, "version"));
}
}
catch (Exception e)
catch (Exception e)
{
{
logger.log(Level.WARNING, "Skipping configuration because invalid ...");
logger.log(Level.WARNING, "Skipping configuration because invalid ...");
e.printStackTrace();
e.printStackTrace();
continue;
continue;
}
}
ServerProperties serverProperties = new ServerProperties();
ServerProperties serverProperties = new ServerProperties();
NodeList serverPropertiesNodeList = eachActionElement.getElementsByTagName("properties").item(0).getChildNodes();
NodeList serverPropertiesNodeList = eachActionElement.getElementsByTagName("properties").item(0).getChildNodes();
for(int j = 0;j<serverPropertiesNodeList.getLength();j++)
for(int j = 0;j<serverPropertiesNodeList.getLength();j++)
{
{
Node eachPropertyNode = serverPropertiesNodeList.item(j);
Node eachPropertyNode = serverPropertiesNodeList.item(j);
if(eachPropertyNode.getNodeType() != Node.ELEMENT_NODE)
if(eachPropertyNode.getNodeType() != Node.ELEMENT_NODE)
continue;
continue;
if(!eachPropertyNode.getNodeName().equals("property"))
if(!eachPropertyNode.getNodeName().equals("property"))
continue;
continue;
Element eachPropertyElement = (Element) eachPropertyNode;
Element eachPropertyElement = (Element) eachPropertyNode;
try
try
{
{
Property property = new Property(XMLConfigHelper.getStringProperty(eachPropertyElement, "name"), Type.STRING);
Property property = new Property(XMLConfigHelper.getStringProperty(eachPropertyElement, "name"), Type.STRING);
property.setRawValue(XMLConfigHelper.getStringProperty(eachPropertyElement, "value"));
property.setRawValue(XMLConfigHelper.getStringProperty(eachPropertyElement, "value"));
serverProperties.addProperty(property);
serverProperties.addProperty(property);
}
}
catch (Exception e)
catch (Exception e)
{
{
logger.log(Level.WARNING, "Skipping property because invalid ...");
logger.log(Level.WARNING, "Skipping property because invalid ...");
e.printStackTrace();
e.printStackTrace();
}
}
}
}
Action action = new Action(ActionType.NORMAL);
Action action = new Action(ActionType.NORMAL);
action.setModuleName(name);
action.setModuleName(name);
action.setVersion(version);
action.setVersion(version);
action.getServerProperties().set(serverProperties);
action.getServerProperties().set(serverProperties);
pluginsConfigs.add(action);
pluginsConfigs.add(action);
}
}
logger.info("Size : "+pluginsConfigs.size());
logger.info("Size : "+pluginsConfigs.size());
Path pluginsDir = Paths.get(pluginsLocation); // Directory with plugins JARs
Path pluginsDir = Paths.get(pluginsLocation); // Directory with plugins JARs
try
try
{
{
// Search for plugins in the plugins directory
// Search for plugins in the plugins directory
ModuleFinder pluginsFinder = ModuleFinder.of(pluginsDir);
ModuleFinder pluginsFinder = ModuleFinder.of(pluginsDir);
// Find all names of all found plugin modules
// Find all names of all found plugin modules
List<String> p = pluginsFinder
List<String> p = pluginsFinder
.findAll()
.findAll()
.stream()
.stream()
.map(ModuleReference::descriptor)
.map(ModuleReference::descriptor)
.map(ModuleDescriptor::name)
.map(ModuleDescriptor::name)
.collect(Collectors.toList());
.collect(Collectors.toList());
// Create configuration that will resolve plugin modules
// Create configuration that will resolve plugin modules
// (verify that the graph of modules is correct)
// (verify that the graph of modules is correct)
Configuration pluginsConfiguration = ModuleLayer
Configuration pluginsConfiguration = ModuleLayer
.boot()
.boot()
.configuration()
.configuration()
.resolve(pluginsFinder, ModuleFinder.of(), p);
.resolve(pluginsFinder, ModuleFinder.of(), p);
// Create a module layer for plugins
// Create a module layer for plugins
ModuleLayer layer = ModuleLayer
ModuleLayer layer = ModuleLayer
.boot()
.boot()
.defineModulesWithOneLoader(pluginsConfiguration, ClassLoader.getSystemClassLoader());
.defineModulesWithOneLoader(pluginsConfiguration, ClassLoader.getSystemClassLoader());
logger.info("Loading plugins from jar ...");
logger.info("Loading plugins from jar ...");
// Now you can use the new module layer to find service implementations in it
// Now you can use the new module layer to find service implementations in it
externalPlugins = ServiceLoader
externalPlugins = ServiceLoader
.load(layer, NormalAction.class).stream()
.load(layer, ExternalPlugin.class).stream()
.map(ServiceLoader.Provider::get)
.map(ServiceLoader.Provider::get)
.collect(Collectors.toList());
.collect(Collectors.toList());
logger.info("...Done!");
logger.info("...Done!");
}
}
catch (Exception e)
catch (Exception e)
{
{
e.printStackTrace();
e.printStackTrace();
throw new MinorException("Error", "Error loading modules\n"+e.getMessage()+"\nPlease fix the errors. Other plugins wont be loaded.");
throw new MinorException("Error", "Error loading modules\n"+e.getMessage()+"\nPlease fix the errors. Other plugins wont be loaded.");
}
}
sortedPlugins = new HashMap<>();
sortedPlugins = new HashMap<>();
for (ExternalPlugin eachPlugin : externalPlugins)
for (ExternalPlugin eachPlugin : externalPlugins)
{
{
try
try
{
{
eachPlugin.setPropertySaver(propertySaver);
eachPlugin.setPropertySaver(propertySaver);
eachPlugin.setServerConnection(serverConnection);
eachPlugin.setServerConnection(serverConnection);
eachPlugin.initProperties();
eachPlugin.initProperties();
logger.info("MODULE : "+eachPlugin.getModuleName());
Action foundAction = null;
Action foundAction = null;
for (Action action : pluginsConfigs) {
for (Action action : pluginsConfigs) {
if (action.getModuleName().equals(eachPlugin.getModuleName())
if (action.getModuleName().equals(eachPlugin.getModuleName())
&& action.getVersion().isEqual(eachPlugin.getVersion())) {
&& action.getVersion().isEqual(eachPlugin.getVersion())) {
foundAction = action;
foundAction = action;
List<Property> eachPluginStoredProperties = action.getServerProperties().get();
List<Property> eachPluginStoredProperties = action.getServerProperties().get();
List<Property> eachPluginCodeProperties = eachPlugin.getServerProperties().get();
List<Property> eachPluginCodeProperties = eachPlugin.getServerProperties().get();
for (int i =0;i< eachPluginCodeProperties.size(); i++) {
for (int i =0;i< eachPluginCodeProperties.size(); i++) {
Property eachPluginCodeProperty = eachPluginCodeProperties.get(i);
Property eachPluginCodeProperty = eachPluginCodeProperties.get(i);
Property foundProp = null;
Property foundProp = null;
for (Property eachPluginStoredProperty : eachPluginStoredProperties) {
for (Property eachPluginStoredProperty : eachPluginStoredProperties) {
if (eachPluginCodeProperty.getName().equals(eachPluginStoredProperty.getName())) {
if (eachPluginCodeProperty.getName().equals(eachPluginStoredProperty.getName())) {
eachPluginCodeProperty.setRawValue(eachPluginStoredProperty.getRawValue());
eachPluginCodeProperty.setRawValue(eachPluginStoredProperty.getRawValue());
foundProp = eachPluginStoredProperty;
foundProp = eachPluginStoredProperty;
}
}
}
}
eachPluginCodeProperties.set(i, eachPluginCodeProperty);
eachPluginCodeProperties.set(i, eachPluginCodeProperty);
if (foundProp != null) {
if (foundProp != null) {
eachPluginStoredProperties.remove(foundProp);
eachPluginStoredProperties.remove(foundProp);
}
}
}
}
eachPlugin.getServerProperties().set(eachPluginCodeProperties);
eachPlugin.getServerProperties().set(eachPluginCodeProperties);
break;
break;
}
}
}
}
if (foundAction != null)
if (foundAction != null)
pluginsConfigs.remove(foundAction);
pluginsConfigs.remove(foundAction);
else
else
{
{
List<Property> eachPluginStoredProperties = eachPlugin.getServerProperties().get();
List<Property> eachPluginStoredProperties = eachPlugin.getServerProperties().get();
for(Property property :eachPluginStoredProperties)
for(Property property :eachPluginStoredProperties)
{
{
if(property.getType() == Type.STRING || property.getType() == Type.INTEGER || property.getType() == Type.DOUBLE)
if(property.getType() == Type.STRING || property.getType() == Type.INTEGER || property.getType() == Type.DOUBLE)
property.setRawValue(property.getDefaultRawValue());
property.setRawValue(property.getDefaultRawValue());
}
}
}
}
if (!sortedPlugins.containsKey(eachPlugin.getCategory())) {
if (!sortedPlugins.containsKey(eachPlugin.getCategory())) {
ArrayList<ExternalPlugin> actions = new ArrayList<>();
ArrayList<ExternalPlugin> actions = new ArrayList<>();
sortedPlugins.put(eachPlugin.getCategory(), actions);
sortedPlugins.put(eachPlugin.getCategory(), actions);
}
}
sortedPlugins.get(eachPlugin.getCategory()).add(eachPlugin);
sortedPlugins.get(eachPlugin.getCategory()).add(eachPlugin);
}
}
catch (Exception e)
catch (Exception e)
{
{
e.printStackTrace();
e.printStackTrace();
errorModules.add(eachPlugin);
errorModules.add(eachPlugin);
errorModuleError.add(e.getMessage());
errorModuleError.add(e.getMessage());
}
}
}
}
try {
try {
saveServerSettings();
saveServerSettings();
} catch (MinorException e) {
} catch (MinorException e) {
e.printStackTrace();
e.printStackTrace();
}
}
logger.log(Level.INFO, "All plugins registered!");
logger.log(Level.INFO, "All plugins registered!");
if(errorModules.size() > 0)
if(errorModules.size() > 0)
{
{
StringBuilder errors = new StringBuilder("The following action modules could not be loaded:");
StringBuilder errors = new StringBuilder("The following action modules could not be loaded:");
for(int i = 0; i<errorModules.size(); i++)
for(int i = 0; i<errorModules.size(); i++)
{
{
externalPlugins.remove(errorModules.get(i));
externalPlugins.remove(errorModules.get(i));
errors.append("\n * ").append(errorModules.get(i).getModuleName()).append("\n(")
errors.append("\n * ").append(errorModules.get(i).getModuleName()).append("\n(")
.append(errorModuleError.get(i)).append(")");
.append(errorModuleError.get(i)).append(")");
}
}
throw new MinorException("Plugins", errors.toString());
throw new MinorException("Plugins", errors.toString());
}
}
for(int i = 0;i<externalPlugins.size();i++)
for(int i = 0;i<externalPlugins.size();i++)
{
{
externalPluginsHashmap.put(externalPlugins.get(i).getModuleName(), i);
externalPluginsHashmap.put(externalPlugins.get(i).getModuleName(), i);
}
}
}
}
/**
/**
* Used to init plugins
* Used to init plugins
*/
*/
public void initPlugins() throws MinorException
public void initPlugins() throws MinorException
{
{
StringBuilder errors = new StringBuilder("There were errors registering the following plugins. As a result, they have been omitted : ");
StringBuilder errors = new StringBuilder("There were errors registering the following plugins. As a result, they have been omitted : ");
boolean isError = false;
boolean isError = false;
for(ExternalPlugin eachPlugin : externalPlugins)
for(ExternalPlugin eachPlugin : externalPlugins)
{
{
try
try
{
{
eachPlugin.initAction();
eachPlugin.initAction();
}
}
catch (Exception e)
catch (Exception e)
{
{
e.printStackTrace();
e.printStackTrace();
isError = true;
isError = true;
errors.append("\n* ")
errors.append("\n* ")
.append(eachPlugin.getName())
.append(eachPlugin.getName())
.append(" - ")
.append(" - ")
.append(eachPlugin.getModuleName())
.append(eachPlugin.getModuleName())
.append("\n");
.append("\n");
if(e instanceof StreamPiException)
if(e instanceof StreamPiException)
errors.append(((MinorException) e).getShortMessage());
errors.append(((MinorException) e).getShortMessage());
errors.append("\n");
errors.append("\n");
}
}
}
}
if(isError)
if(isError)
{
{
throw new MinorException("Plugin init error", errors.toString());
throw new MinorException("Plugin init error", errors.toString());
}
}
}
}
HashMap<String, ArrayList<ExternalPlugin>> sortedPlugins;
HashMap<String, ArrayList<ExternalPlugin>> sortedPlugins;
/**
/**
* Gets list of sorted plugins
* Gets list of sorted plugins
*
*
* @return Hashmap with category key, and list of plugins of each category
* @return Hashmap with category key, and list of plugins of each category
*/
*/
public HashMap<String, ArrayList<ExternalPlugin>> getSortedPlugins()
public HashMap<String, ArrayList<ExternalPlugin>> getSortedPlugins()
{
{
return sortedPlugins;
return sortedPlugins;
}
}
/**
/**
* @return Gets actions element from the config.xml in plugins folder
* @return Gets actions element from the config.xml in plugins folder
*/
*/
private Element getActionsElement()
private Element getActionsElement()
{
{
return (Element) document.getElementsByTagName("actions").item(0);
return (Element) document.getElementsByTagName("actions").item(0);
}
}
/**
/**
* Saves ServerProperties of every plugin in config.xml in plugins folder
* Saves ServerProperties of every plugin in config.xml in plugins folder
*
*
* @throws MinorException Thrown when failed to save settings
* @throws MinorException Thrown when failed to save settings
*/
*/
public void saveServerSettings() throws MinorException
public void saveServerSettings() throws MinorException
{
{
XMLConfigHelper.removeChilds(getActionsElement());
XMLConfigHelper.removeChilds(getActionsElement());
for(ExternalPlugin normalAction : externalPlugins)
for(ExternalPlugin normalAction : externalPlugins)
{
{
Element actionElement = document.createElement("action");
Element actionElement = document.createElement("action");
getActionsElement().appendChild(actionElement);
getActionsElement().appendChild(actionElement);
Element moduleNameElement = document.createElement("module-name");
Element moduleNameElement = document.createElement("module-name");
moduleNameElement.setTextContent(normalAction.getModuleName());
moduleNameElement.setTextContent(normalAction.getModuleName());
actionElement.appendChild(moduleNameElement);
actionElement.appendChild(moduleNameElement);
Element versionElement = document.createElement("version");
Element versionElement = document.createElement("version");
versionElement.setTextContent(normalAction.getVersion().getText());
versionElement.setTextContent(normalAction.getVersion().getText());
actionElement.appendChild(versionElement);
actionElement.appendChild(versionElement);
Element propertiesElement = document.createElement("properties");
Element propertiesElement = document.createElement("properties");
actionElement.appendChild(propertiesElement);
actionElement.appendChild(propertiesElement);
for(String key : normalAction.getServerProperties().getNames())
for(String key : normalAction.getServerProperties().getNames())
{
{
for(Property eachProperty : normalAction.getServerProperties().getMultipleProperties(key))
for(Property eachProperty : normalAction.getServerProperties().getMultipleProperties(key))
{
{
Element propertyElement = document.createElement("property");
Element propertyElement = document.createElement("property");
propertiesElement.appendChild(propertyElement);
propertiesElement.appendChild(propertyElement);
Element nameElement = document.createElement("name");
Element nameElement = document.createElement("name");
nameElement.setTextContent(eachProperty.getName());
nameElement.setTextContent(eachProperty.getName());
propertyElement.appendChild(nameElement);
propertyElement.appendChild(nameElement);
Element valueElement = document.createElement("value");
Element valueElement = document.createElement("value");
valueElement.setTextContent(eachProperty.getRawValue());
valueElement.setTextContent(eachProperty.getRawValue());
propertyElement.appendChild(valueElement);
propertyElement.appendChild(valueElement);
}
}
}
}
}
}
save();
save();
}
}
private PropertySaver propertySaver = null;
private PropertySaver propertySaver = null;
/**
/**
* Set PropertySaver class
* Set PropertySaver class
* @param propertySaver instance of PropertySaver
* @param propertySaver instance of PropertySaver
*/
*/
public void setPropertySaver(PropertySaver propertySaver)
public void setPropertySaver(PropertySaver propertySaver)
{
{
this.propertySaver = propertySaver;
this.propertySaver = propertySaver;
}
}
private ServerConnection serverConnection = null;
private ServerConnection serverConnection = null;
/**
/**
* Set setServerConnection class
* Set setServerConnection class
* @param serverConnection instance of ServerConnection
* @param serverConnection instance of ServerConnection
*/
*/
public void setServerConnection(ServerConnection serverConnection)
public void setServerConnection(ServerConnection serverConnection)
{
{
this.serverConnection = serverConnection;
this.serverConnection = serverConnection;
}
}
/**
/**
* Get plugin from index from list
* Get plugin from index from list
*
*
* @param index of plugin
* @param index of plugin
* @return found plugin
* @return found plugin
*/
*/
public ExternalPlugin getActionFromIndex(int index)
public ExternalPlugin getActionFromIndex(int index)
{
{
return externalPlugins.get(index);
return externalPlugins.get(index);
}
}
/**
/**
* Calls onShutDown method in every plugin
* Calls onShutDown method in every plugin
*/
*/
public void shutDownActions()
public void shutDownActions()
{
{
if(externalPlugins != null)
if(externalPlugins != null)
{
{
for(ExternalPlugin eachPlugin : externalPlugins)
for(ExternalPlugin eachPlugin : externalPlugins)
{
{
try
try
{
{
eachPlugin.onShutDown();
eachPlugin.onShutDown();
}
}
catch (Exception e)
catch (Exception e)
{
{
e.printStackTrace();
e.printStackTrace();
}
}
}
}
externalPlugins.clear();
externalPlugins.clear();
}
}
}
}
/**
/**
* Saves all Server Properties of each Plugin in config.xml in Plugins folder
* Saves all Server Properties of each Plugin in config.xml in Plugins folder
* @throws MinorException thrown when failed to save
* @throws MinorException thrown when failed to save
*/
*/
public void save() throws MinorException
public void save() throws MinorException
{
{
try
try
{
{
Transformer transformer = TransformerFactory.newInstance().newTransformer();
Transformer transformer = TransformerFactory.newInstance().newTransformer();
Result output = new StreamResult(configFile);
Result output = new StreamResult(configFile);
Source input = new DOMSource(document);
Source input = new DOMSource(document);
transformer.transform(input, output);
transformer.transform(input, output);
}
}
catch (Exception e)
catch (Exception e)
{
{
throw new MinorException("Config", "unable to save server plugins settings");
throw new MinorException("Config", "unable to save server plugins settings");
}
}
}
}
}
}
package com.stream_pi.server.connection;
package com.stream_pi.server.connection;
import com.stream_pi.action_api.action.Action;
import com.stream_pi.action_api.action.Action;
import com.stream_pi.action_api.action.ActionType;
import com.stream_pi.action_api.action.ActionType;
import com.stream_pi.action_api.action.DisplayTextAlignment;
import com.stream_pi.action_api.action.DisplayTextAlignment;
import com.stream_pi.action_api.action.Location;
import com.stream_pi.action_api.action.Location;
import com.stream_pi.action_api.actionproperty.ClientProperties;
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.Property;
import com.stream_pi.action_api.actionproperty.property.Type;
import com.stream_pi.action_api.actionproperty.property.Type;
import com.stream_pi.action_api.normalaction.ExternalPlugin;
import com.stream_pi.action_api.normalaction.ExternalPlugin;
import com.stream_pi.action_api.normalaction.NormalAction;
import com.stream_pi.action_api.normalaction.NormalAction;
import com.stream_pi.action_api.normalaction.ToggleAction;
import com.stream_pi.action_api.normalaction.ToggleAction;
import com.stream_pi.server.action.ExternalPlugins;
import com.stream_pi.server.action.ExternalPlugins;
import com.stream_pi.server.client.Client;
import com.stream_pi.server.client.Client;
import com.stream_pi.server.client.ClientProfile;
import com.stream_pi.server.client.ClientProfile;
import com.stream_pi.server.client.ClientTheme;
import com.stream_pi.server.client.ClientTheme;
import com.stream_pi.server.info.ServerInfo;
import com.stream_pi.server.info.ServerInfo;
import com.stream_pi.server.window.ExceptionAndAlertHandler;
import com.stream_pi.server.window.ExceptionAndAlertHandler;
import com.stream_pi.util.alert.StreamPiAlert;
import com.stream_pi.util.alert.StreamPiAlert;
import com.stream_pi.util.alert.StreamPiAlertType;
import com.stream_pi.util.alert.StreamPiAlertType;
import com.stream_pi.util.comms.Message;
import com.stream_pi.util.comms.Message;
import com.stream_pi.util.exception.MinorException;
import com.stream_pi.util.exception.MinorException;
import com.stream_pi.util.exception.SevereException;
import com.stream_pi.util.exception.SevereException;
import com.stream_pi.util.exception.StreamPiException;
import com.stream_pi.util.exception.StreamPiException;
import com.stream_pi.util.platform.Platform;
import com.stream_pi.util.platform.Platform;
import com.stream_pi.util.platform.ReleaseStatus;
import com.stream_pi.util.platform.ReleaseStatus;
import com.stream_pi.util.version.Version;
import com.stream_pi.util.version.Version;
import javafx.concurrent.Task;
import javafx.concurrent.Task;
import java.io.*;
import java.io.*;
import java.net.Socket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.logging.Logger;
public class ClientConnection extends Thread
public class ClientConnection extends Thread
{
{
private Socket socket;
private Socket socket;
private ServerListener serverListener;
private ServerListener serverListener;
private AtomicBoolean stop = new AtomicBoolean(false);
private AtomicBoolean stop = new AtomicBoolean(false);
private ObjectOutputStream oos;
private ObjectOutputStream oos;
private ObjectInputStream ois;
private ObjectInputStream ois;
private Logger logger;
private Logger logger;
private Client client = null;
private Client client = null;
private ExceptionAndAlertHandler exceptionAndAlertHandler;
private ExceptionAndAlertHandler exceptionAndAlertHandler;
public ClientConnection(Socket socket, ServerListener serverListener, ExceptionAndAlertHandler exceptionAndAlertHandler)
public ClientConnection(Socket socket, ServerListener serverListener, ExceptionAndAlertHandler exceptionAndAlertHandler)
{
{
this.exceptionAndAlertHandler = exceptionAndAlertHandler;
this.exceptionAndAlertHandler = exceptionAndAlertHandler;
this.socket = socket;
this.socket = socket;
this.serverListener = serverListener;
this.serverListener = serverListener;
logger = Logger.getLogger(ClientConnection.class.getName());
logger = Logger.getLogger(ClientConnection.class.getName());
try
try
{
{
oos = new ObjectOutputStream(socket.getOutputStream());
oos = new ObjectOutputStream(socket.getOutputStream());
ois = new ObjectInputStream(socket.getInputStream());
ois = new ObjectInputStream(socket.getInputStream());
} catch (IOException e) {
} catch (IOException e) {
e.printStackTrace();
e.printStackTrace();
exceptionAndAlertHandler.handleMinorException(new MinorException("Unable to start socket streams"));
exceptionAndAlertHandler.handleMinorException(new MinorException("Unable to start socket streams"));
}
}
start();
start();
}
}
public synchronized void exit()
public synchronized void exit()
{
{
if(stop.get())
if(stop.get())
return;
return;
logger.info("Stopping ...");
logger.info("Stopping ...");
try
try
{
{
if(socket !=null)
if(socket !=null)
{
{
logger.info("Stopping connection "+socket.getRemoteSocketAddress());
logger.info("Stopping connection "+socket.getRemoteSocketAddress());
disconnect();
disconnect();
}
}
}
}
catch (SevereException e)
catch (SevereException e)
{
{
e.printStackTrace();
e.printStackTrace();
exceptionAndAlertHandler.handleSevereException(e);
exceptionAndAlertHandler.handleSevereException(e);
}
}
}
}
public synchronized void exitAndRemove()
public synchronized void exitAndRemove()
{
{
exit();
exit();
removeConnection();
removeConnection();
serverListener.clearTemp();
serverListener.clearTemp();
}
}
public void removeConnection()
public void removeConnection()
{
{
ClientConnections.getInstance().removeConnection(this);
ClientConnections.getInstance().removeConnection(this);
}
}
public void sendIcon(String profileID, String actionID, String state, byte[] icon) throws SevereException
public void sendIcon(String profileID, String actionID, String state, byte[] icon) throws SevereException
{
{
try
try
{
{
Thread.sleep(50);
Thread.sleep(50);
}
}
catch (InterruptedException e)
catch (InterruptedException e)
{
{
e.printStackTrace();
e.printStackTrace();
}
}
Message message = new Message("action_icon");
Message message = new Message("action_icon");
message.setStringArrValue(profileID, actionID, state);
message.setStringArrValue(profileID, actionID, state);
message.setByteArrValue(icon);
message.setByteArrValue(icon);
sendMessage(message);
sendMessage(message);
}
}
public void initAfterConnectionQueryReceive(Message message) throws StreamPiException
public void initAfterConnectionQueryReceive(Message message) throws StreamPiException
{
{
String[] ar = message.getStringArrValue();
String[] ar = message.getStringArrValue();
logger.info("Setting up client object ...");
logger.info("Setting up client object ...");
Version clientVersion;
Version clientVersion;
Version commsStandard;
Version commsStandard;
Version themesStandard;
Version themesStandard;
ReleaseStatus releaseStatus;
ReleaseStatus releaseStatus;
try
try
{
{
clientVersion = new Version(ar[0]);
clientVersion = new Version(ar[0]);
releaseStatus = ReleaseStatus.valueOf(ar[1]);
releaseStatus = ReleaseStatus.valueOf(ar[1]);
commsStandard = new Version(ar[2]);
commsStandard = new Version(ar[2]);
themesStandard = new Version(ar[3]);
themesStandard = new Version(ar[3]);
}
}
catch (MinorException e)
catch (MinorException e)
{
{
exitAndRemove();
exitAndRemove();
throw new MinorException(e.getShortMessage()+" (client '"+socket.getRemoteSocketAddress()+"' )");
throw new MinorException(e.getShortMessage()+" (client '"+socket.getRemoteSocketAddress()+"' )");
}
}
if(!commsStandard.isEqual(ServerInfo.getInstance().getCommStandardVersion()))
if(!commsStandard.isEqual(ServerInfo.getInstance().getCommStandardVersion()))
{
{
String errTxt = "Server and client Communication standards do not match. Make sure you are on the latest version of server and client.\n" +
String errTxt = "Server and client Communication standards do not match. Make sure you are on the latest version of server and client.\n" +
"Server Comms. Standard : "+ServerInfo.getInstance().getCommStandardVersion().getText()+
"Server Comms. Standard : "+ServerInfo.getInstance().getCommStandardVersion().getText()+
"\nclient Comms. Standard : "+commsStandard.getText();
"\nclient Comms. Standard : "+commsStandard.getText();
disconnect(errTxt);
disconnect(errTxt);
throw new MinorException(errTxt);
throw new MinorException(errTxt);
}
}
client = new Client(clientVersion, releaseStatus, commsStandard, themesStandard, ar[4], Platform.valueOf(ar[7]), socket.getRemoteSocketAddress());
client = new Client(clientVersion, releaseStatus, commsStandard, themesStandard, ar[4], Platform.valueOf(ar[7]), socket.getRemoteSocketAddress());
client.setDisplayWidth(Double.parseDouble(ar[5]));
client.setDisplayWidth(Double.parseDouble(ar[5]));
client.setDisplayHeight(Double.parseDouble(ar[6]));
client.setDisplayHeight(Double.parseDouble(ar[6]));
client.setDefaultProfileID(ar[8]);
client.setDefaultProfileID(ar[8]);
client.setDefaultThemeFullName(ar[9]);
client.setDefaultThemeFullName(ar[9]);
//call get profiles command.
//call get profiles command.
serverListener.clearTemp();
serverListener.clearTemp();
}
}
public synchronized Client getClient()
public synchronized Client getClient()
{
{
return client;
return client;
}
}
@Override
@Override
public void run() {
public void run() {
try {
try {
initAfterConnectionQuerySend();
initAfterConnectionQuerySend();
} catch (SevereException e) {
} catch (SevereException e) {
e.printStackTrace();
e.printStackTrace();
exceptionAndAlertHandler.handleSevereException(e);
exceptionAndAlertHandler.handleSevereException(e);
exitAndRemove();
exitAndRemove();
return;
return;
}
}
try
try
{
{
while(!stop.get())
while(!stop.get())
{
{
try
try
{
{
Message message = (Message) ois.readObject();
Message message = (Message) ois.readObject();
String header = message.getHeader();
String header = message.getHeader();
switch (header)
switch (header)
{
{
case "action_icon" : onActionIconReceived(message);
case "action_icon" : onActionIconReceived(message);
break;
break;
case "disconnect" : clientDisconnected(message);
case "disconnect" : clientDisconnected(message);
break;
break;
case "client_details" : initAfterConnectionQueryReceive(message);
case "client_details" : initAfterConnectionQueryReceive(message);
getProfilesFromClient();
getProfilesFromClient();
getThemesFromClient();
getThemesFromClient();
break;
break;
case "profiles" : registerProfilesFromClient(message);
case "profiles" : registerProfilesFromClient(message);
break;
break;
case "profile_details" : registerProfileDetailsFromClient(message);
case "profile_details" : registerProfileDetailsFromClient(message);
break;
break;
case "action_details" : registerActionToProfile(message);
case "action_details" : registerActionToProfile(message);
break;
break;
case "themes": registerThemes(message);
case "themes": registerThemes(message);
break;
break;
case "action_clicked": actionClicked(message);
case "action_clicked": actionClicked(message);
break;
break;
default: logger.warning("Command '"+header+"' does not match records. Make sure client and server versions are equal.");
default: logger.warning("Command '"+header+"' does not match records. Make sure client and server versions are equal.");
}
}
}
}
catch (IOException | ClassNotFoundException e)
catch (IOException | ClassNotFoundException e)
{
{
logger.log(Level.SEVERE, e.getMessage());
logger.log(Level.SEVERE, e.getMessage());
e.printStackTrace();
e.printStackTrace();
serverListener.clearTemp();
serverListener.clearTemp();
if(!stop.get())
if(!stop.get())
{
{
removeConnection();
removeConnection();
throw new MinorException("Accidentally disconnected from "+getClient().getNickName()+".");
throw new MinorException("Accidentally disconnected from "+getClient().getNickName()+".");
}
}
exitAndRemove();
exitAndRemove();
return;
return;
}
}
}
}
}
}
catch (StreamPiException e)
catch (StreamPiException e)
{
{
e.printStackTrace();
e.printStackTrace();
if(e instanceof MinorException)
if(e instanceof MinorException)
exceptionAndAlertHandler.handleMinorException((MinorException) e);
exceptionAndAlertHandler.handleMinorException((MinorException) e);
else if (e instanceof SevereException)
else if (e instanceof SevereException)
exceptionAndAlertHandler.handleSevereException((SevereException) e);
exceptionAndAlertHandler.handleSevereException((SevereException) e);
}
}
}
}
// commands
// commands
private void onActionIconReceived(Message message) throws MinorException
private void onActionIconReceived(Message message) throws MinorException
{
{
String[] s = message.getStringArrValue();
String[] s = message.getStringArrValue();
String profileID = s[0];
String profileID = s[0];
String actionID = s[1];
String actionID = s[1];
String iconState = s[2];
String iconState = s[2];
getClient()
getClient()
.getProfileByID(profileID)
.getProfileByID(profileID)
.getActionByID(actionID)
.getActionByID(actionID)
.addIcon(iconState,message.getByteArrValue());
.addIcon(iconState,message.getByteArrValue());
}
}
public void initAfterConnectionQuerySend() throws SevereException
public void initAfterConnectionQuerySend() throws SevereException
{
{
logger.info("Asking client details ...");
logger.info("Asking client details ...");
sendMessage(new Message("get_client_details"));
sendMessage(new Message("get_client_details"));
}
}
public void disconnect() throws SevereException {
public void disconnect() throws SevereException {
disconnect("");
disconnect("");
}
}
public void disconnect(String message) throws SevereException {
public void disconnect(String message) throws SevereException {
if(stop.get())
if(stop.get())
return;
return;
stop.set(true);
stop.set(true);
logger.info("Sending client disconnect message ...");
logger.info("Sending client disconnect message ...");
Message m = new Message("disconnect");
Message m = new Message("disconnect");
m.setStringValue(message);
m.setStringValue(message);
sendMessage(m);
sendMessage(m);
try
try
{
{
if(!socket.isClosed())
if(!socket.isClosed())
socket.close();
socket.close();
}
}
catch (IOException e)
catch (IOException e)
{
{
e.printStackTrace();
e.printStackTrace();
throw new SevereException("Unable to close socket");
throw new SevereException("Unable to close socket");
}
}
}
}
public synchronized void sendMessage(Message message) throws SevereException
public synchronized void sendMessage(Message message) throws SevereException
{
{
try
try
{
{
oos.writeObject(message);
oos.writeObject(message);
oos.flush();
oos.flush();
}
}
catch (IOException e)
catch (IOException e)
{
{
e.printStackTrace();
e.printStackTrace();
throw new SevereException("Unable to write to io Stream!");
throw new SevereException("Unable to write to io Stream!");
}
}
}
}
public void clientDisconnected(Message message)
public void clientDisconnected(Message message)
{
{
stop.set(true);
stop.set(true);
String txt = "Disconnected!";
String txt = "Disconnected!";
String msg = message.getStringValue();
String msg = message.getStringValue();
if(!msg.isBlank())
if(!msg.isBlank())
txt = "Message : "+msg;
txt = "Message : "+msg;
new StreamPiAlert("Disconnected from "+getClient().getNickName()+".", txt, StreamPiAlertType.WARNING).show();;
new StreamPiAlert("Disconnected from "+getClient().getNickName()+".", txt, StreamPiAlertType.WARNING).show();;
exitAndRemove();
exitAndRemove();
}
}
public void getProfilesFromClient() throws StreamPiException
public void getProfilesFromClient() throws StreamPiException
{
{
logger.info("Asking client to send profiles ...");
logger.info("Asking client to send profiles ...");
sendMessage(new Message("get_profiles"));
sendMessage(new Message("get_profiles"));
}
}
public void getThemesFromClient() throws StreamPiException
public void getThemesFromClient() throws StreamPiException
{
{
logger.info("Asking clients to send themes ...");
logger.info("Asking clients to send themes ...");
sendMessage(new Message("get_themes"));
sendMessage(new Message("get_themes"));
}
}
public void registerThemes(Message message)
public void registerThemes(Message message)
{
{
String[] r = message.getStringArrValue();
String[] r = message.getStringArrValue();
for(int i =0; i<(r.length);i+=4)
for(int i =0; i<(r.length);i+=4)
{
{
ClientTheme clientTheme = new ClientTheme(
ClientTheme clientTheme = new ClientTheme(
r[i],
r[i],
r[i+1],
r[i+1],
r[i+2],
r[i+2],
r[i+3]
r[i+3]
);
);
try
try
{
{
getClient().addTheme(clientTheme);
getClient().addTheme(clientTheme);
}
}
catch (CloneNotSupportedException e)
catch (CloneNotSupportedException e)
{
{
logger.log(Level.SEVERE, e.getMessage());
logger.log(Level.SEVERE, e.getMessage());
e.printStackTrace();
e.printStackTrace();
}
}
}
}
}
}
public void registerProfilesFromClient(Message message) throws StreamPiException
public void registerProfilesFromClient(Message message) throws StreamPiException
{
{
logger.info("Registering profiles ...");
logger.info("Registering profiles ...");
String[] r = message.getStringArrValue();
String[] r = message.getStringArrValue();
for (String profileID : r) {
for (String profileID : r) {
getProfileDetailsFromClient(profileID);
getProfileDetailsFromClient(profileID);
}
}
}
}
public void getProfileDetailsFromClient(String ID) throws StreamPiException
public void getProfileDetailsFromClient(String ID) throws StreamPiException
{
{
logger.info("Asking client to send details of profile : "+ID);
logger.info("Asking client to send details of profile : "+ID);
Message message = new Message("get_profile_details");
Message message = new Message("get_profile_details");
message.setStringValue(ID);
message.setStringValue(ID);
sendMessage(message);
sendMessage(message);
}
}
public void registerProfileDetailsFromClient(Message message)
public void registerProfileDetailsFromClient(Message message)
{
{
String[] r = message.getStringArrValue();
String[] r = message.getStringArrValue();
String ID = r[0];
String ID = r[0];
logger.info("Registering details for profile : "+ID);
logger.info("Registering details for profile : "+ID);
String name = r[1];
String name = r[1];
int rows = Integer.parseInt(r[2]);
int rows = Integer.parseInt(r[2]);
int cols = Integer.parseInt(r[3]);
int cols = Integer.parseInt(r[3]);
int actionSize = Integer.parseInt(r[4]);
int actionSize = Integer.parseInt(r[4]);
int actionGap = Integer.parseInt(r[5]);
int actionGap = Integer.parseInt(r[5]);
ClientProfile clientProfile = new ClientProfile(name, ID, rows, cols, actionSize, actionGap);
ClientProfile clientProfile = new ClientProfile(name, ID, rows, cols, actionSize, actionGap);
logger.info("Added client profile "+clientProfile.getName());
logger.info("Added client profile "+clientProfile.getName());
try
try
{
{
getClient().addProfile(clientProfile);
getClient().addProfile(clientProfile);
}
}
catch (CloneNotSupportedException e)
catch (CloneNotSupportedException e)
{
{
logger.severe(e.getMessage());
logger.severe(e.getMessage());
e.printStackTrace();
e.printStackTrace();
}
}
serverListener.clearTemp();
serverListener.clearTemp();
}
}
public synchronized void registerActionToProfile(Message message) throws StreamPiException
public synchronized void registerActionToProfile(Message message) throws StreamPiException
{
{
String[] r = message.getStringArrValue();
String[] r = message.getStringArrValue();
String profileID = r[0];
String profileID = r[0];
String ID = r[1];
String ID = r[1];
ActionType actionType = ActionType.valueOf(r[2]);
ActionType actionType = ActionType.valueOf(r[2]);
//3 - Version
//3 - Version
//4 - ModuleName
//4 - ModuleName
//display
//display
String bgColorHex = r[5];
String bgColorHex = r[5];
//icon
//icon
String[] allIconStateNames = r[6].split("::");
String[] allIconStateNames = r[6].split("::");
String defaultIconState = r[7];
String defaultIconState = r[7];
//text
//text
boolean isShowDisplayText = r[8].equals("true");
boolean isShowDisplayText = r[8].equals("true");
String displayFontColor = r[9];
String displayFontColor = r[9];
String displayText = r[10];
String displayText = r[10];
DisplayTextAlignment displayTextAlignment = DisplayTextAlignment.valueOf(r[11]);
DisplayTextAlignment displayTextAlignment = DisplayTextAlignment.valueOf(r[11]);
//location
//location
String row = r[12];
String row = r[12];
String col = r[13];
String col = r[13];
Location location = new Location(Integer.parseInt(row), Integer.parseInt(col));
Location location = new Location(Integer.parseInt(row), Integer.parseInt(col));
Action action = new Action(ID, actionType);
Action action = new Action(ID, actionType);
action.setBgColourHex(bgColorHex);
action.setBgColourHex(bgColorHex);
action.setCurrentIconState(defaultIconState);
action.setCurrentIconState(defaultIconState);
action.setShowDisplayText(isShowDisplayText);
action.setShowDisplayText(isShowDisplayText);
action.setDisplayTextFontColourHex(displayFontColor);
action.setDisplayTextFontColourHex(displayFontColor);
action.setDisplayText(displayText);
action.setDisplayText(displayText);
action.setDisplayTextAlignment(displayTextAlignment);
action.setDisplayTextAlignment(displayTextAlignment);
action.setLocation(location);
action.setLocation(location);
String root = r[14];
String root = r[14];
action.setParent(root);
action.setParent(root);
action.setDelayBeforeExecuting(Integer.parseInt(r[15]));
action.setDelayBeforeExecuting(Integer.parseInt(r[15]));
//client properties
//client properties
int clientPropertiesSize = Integer.parseInt(r[16]);
int clientPropertiesSize = Integer.parseInt(r[16]);
ClientProperties clientProperties = new ClientProperties();
ClientProperties clientProperties = new ClientProperties();
if(actionType == ActionType.FOLDER)
if(actionType == ActionType.FOLDER)
clientProperties.setDuplicatePropertyAllowed(true);
clientProperties.setDuplicatePropertyAllowed(true);
for(int i = 17;i<((clientPropertiesSize*2) + 17); i+=2)
for(int i = 17;i<((clientPropertiesSize*2) + 17); i+=2)
{
{
Property property = new Property(r[i], Type.STRING);
Property property = new Property(r[i], Type.STRING);
property.setRawValue(r[i+1]);
property.setRawValue(r[i+1]);
clientProperties.addProperty(property);
clientProperties.addProperty(property);
}
}
action.setClientProperties(clientProperties);
action.setClientProperties(clientProperties);
action.setModuleName(r[4]);
action.setModuleName(r[4]);
//set up action
//set up action
//action toBeAdded = null;
//action toBeAdded = null;
if(actionType == ActionType.NORMAL)
if(actionType == ActionType.NORMAL || actionType == ActionType.TOGGLE)
{
{
ExternalPlugin actionCopy = ExternalPlugins.getInstance().getPluginByModuleName(r[4]);
ExternalPlugin actionCopy = ExternalPlugins.getInstance().getPluginByModuleName(r[4]);
if(actionCopy == null)
if(actionCopy == null)
{
{
action.setInvalid(true);
action.setInvalid(true);
}
}
else
else
{
{
action.setVersion(new Version(r[3]));
action.setVersion(new Version(r[3]));
//action.setHelpLink(actionCopy.getHelpLink());
//action.setHelpLink(actionCopy.getHelpLink());
if(actionCopy.getVersion().getMajor() != action.getVersion().getMajor())
if(actionCopy.getVersion().getMajor() != action.getVersion().getMajor())
{
{
action.setInvalid(true);
action.setInvalid(true);
}
}
else
else
{
{
action.setName(actionCopy.getName());
action.setName(actionCopy.getName());
ClientProperties finalClientProperties = new ClientProperties();
ClientProperties finalClientProperties = new ClientProperties();
for(Property property : actionCopy.getClientProperties().get())
for(Property property : actionCopy.getClientProperties().get())
{
{
for(int i = 0;i<action.getClientProperties().getSize();i++)
for(int i = 0;i<action.getClientProperties().getSize();i++)
{
{
Property property1 = action.getClientProperties().get().get(i);
Property property1 = action.getClientProperties().get().get(i);
if (property.getName().equals(property1.getName()))
if (property.getName().equals(property1.getName()))
{
{
property.setRawValue(property1.getRawValue());
property.setRawValue(property1.getRawValue());
finalClientProperties.addProperty(property);
finalClientProperties.addProperty(property);
}
}
}
}
}
}
action.setClientProperties(finalClientProperties);
action.setClientProperties(finalClientProperties);
}
}
}
}
}
}
try
try
{
{
getClient().getProfileByID(profileID).addAction(action);
getClient().getProfileByID(profileID).addAction(action);
}
}
catch (CloneNotSupportedException e)
catch (CloneNotSupportedException e)
{
{
e.printStackTrace();
e.printStackTrace();
exceptionAndAlertHandler.handleMinorException(new MinorException("action", "Unable to clone"));
exceptionAndAlertHandler.handleMinorException(new MinorException("action", "Unable to clone"));
}
}
}
}
public void saveActionDetails(String profileID, Action action) throws SevereException
public void saveActionDetails(String profileID, Action action) throws SevereException
{
{
ArrayList<String> a = new ArrayList<>();
ArrayList<String> a = new ArrayList<>();
a.add(profileID);
a.add(profileID);
a.add(action.getID());
a.add(action.getID());
a.add(action.getActionType()+"");
a.add(action.getActionType()+"");
if(action.getActionType() == ActionType.NORMAL)
if(action.getActionType() == ActionType.NORMAL)
{
{
a.add(action.getVersion().getText());
a.add(action.getVersion().getText());
System.out.println("VERSION :sdd "+action.getVersion().getText());
System.out.println("VERSION :sdd "+action.getVersion().getText());
}
}
else
else
{
{
a.add("no");
a.add("no");
}
}
if(action.getActionType() == ActionType.NORMAL)
if(action.getActionType() == ActionType.NORMAL)
{
{
a.add(action.getModuleName());
a.add(action.getModuleName());
}
}
else
else
{
{
a.add("nut");
a.add("nut");
}
}
//display
//display
a.add(action.getBgColourHex());
a.add(action.getBgColourHex());
//icon
//icon
StringBuilder allIconStatesNames = new StringBuilder();
StringBuilder allIconStatesNames = new StringBuilder();
for(String eachState : action.getIcons().keySet())
for(String eachState : action.getIcons().keySet())
{
{
allIconStatesNames.append(eachState).append("::");
allIconStatesNames.append(eachState).append("::");
}
}
a.add(allIconStatesNames.toString());
a.add(allIconStatesNames.toString());
a.add(action.getCurrentIconState());
a.add(action.getCurrentIconState());
//text
//text
a.add(action.isShowDisplayText()+"");
a.add(action.isShowDisplayText()+"");
a.add(action.getDisplayTextFontColourHex());
a.add(action.getDisplayTextFontColourHex());
a.add(action.getDisplayText());
a.add(action.getDisplayText());
a.add(action.getDisplayTextAlignment()+"");
a.add(action.getDisplayTextAlignment()+"");
//location
//location
if(action.getLocation() == null)
if(action.getLocation() == null)
{
{
a.add("-1");
a.add("-1");
a.add("-1");
a.add("-1");
}
}
else
else
{
{
a.add(action.getLocation().getRow()+"");
a.add(action.getLocation().getRow()+"");
a.add(action.getLocation().getCol()+"");
a.add(action.getLocation().getCol()+"");
}
}
a.add(action.getParent());
a.add(action.getParent());
a.add(action.getDelayBeforeExecuting()+"");
a.add(action.getDelayBeforeExecuting()+"");
//client properties
//client properties
ClientProperties clientProperties = action.getClientProperties();
ClientProperties clientProperties = action.getClientProperties();
a.add(clientProperties.getSize()+"");
a.add(clientProperties.getSize()+"");
for(Property property : clientProperties.get())
for(Property property : clientProperties.get())
{
{
a.add(property.getName());
a.add(property.getName());
a.add(property.getRawValue());
a.add(property.getRawValue());
}
}
Message message = new Message("save_action_details");
Message message = new Message("save_action_details");
String[] x = new String[a.size()];
String[] x = new String[a.size()];
x = a.toArray(x);
x = a.toArray(x);
message.setStringArrValue(x);
message.setStringArrValue(x);
sendMessage(message);
sendMessage(message);
}
}
public void deleteAction(String profileID, String actionID) throws SevereException
public void deleteAction(String profileID, String actionID) throws SevereException
{
{
Message message = new Message("delete_action");
Message message = new Message("delete_action");
message.setStringArrValue(profileID, actionID);
message.setStringArrValue(profileID, actionID);
sendMessage(message);
sendMessage(message);
}
}
public void saveClientDetails(String clientNickname, String defaultProfileID,
public void saveClientDetails(String clientNickname, String defaultProfileID,
String defaultThemeFullName) throws SevereException
String defaultThemeFullName) throws SevereException
{
{
Message message = new Message("save_client_details");
Message message = new Message("save_client_details");
message.setStringArrValue(
message.setStringArrValue(
clientNickname,
clientNickname,
defaultProfileID,
defaultProfileID,
defaultThemeFullName
defaultThemeFullName
);
);
sendMessage(message);
sendMessage(message);
client.setNickName(clientNickname);
client.setNickName(clientNickname);
client.setDefaultProfileID(defaultProfileID);
client.setDefaultProfileID(defaultProfileID);
client.setDefaultThemeFullName(defaultThemeFullName);
client.setDefaultThemeFullName(defaultThemeFullName);
}
}
public void saveProfileDetails(ClientProfile clientProfile) throws SevereException, CloneNotSupportedException {
public void saveProfileDetails(ClientProfile clientProfile) throws SevereException, CloneNotSupportedException {
if(client.getProfileByID(clientProfile.getID()) !=null)
if(client.getProfileByID(clientProfile.getID()) !=null)
{
{
client.getProfileByID(clientProfile.getID()).setName(clientProfile.getName());
client.getProfileByID(clientProfile.getID()).setName(clientProfile.getName());
client.getProfileByID(clientProfile.getID()).setRows(clientProfile.getRows());
client.getProfileByID(clientProfile.getID()).setRows(clientProfile.getRows());
client.getProfileByID(clientProfile.getID()).setCols(clientProfile.getCols());
client.getProfileByID(clientProfile.getID()).setCols(clientProfile.getCols());
client.getProfileByID(clientProfile.getID()).setActionSize(clientProfile.getActionSize());
client.getProfileByID(clientProfile.getID()).setActionSize(clientProfile.getActionSize());
client.getProfileByID(clientProfile.getID()).setActionGap(clientProfile.getActionGap());
client.getProfileByID(clientProfile.getID()).setActionGap(clientProfile.getActionGap());
}
}
else
else
client.addProfile(clientProfile);
client.addProfile(clientProfile);
Message message = new Message("save_client_profile");
Message message = new Message("save_client_profile");
message.setStringArrValue(
message.setStringArrValue(
clientProfile.getID(),
clientProfile.getID(),
clientProfile.getName(),
clientProfile.getName(),
clientProfile.getRows()+"",
clientProfile.getRows()+"",
clientProfile.getCols()+"",
clientProfile.getCols()+"",
clientProfile.getActionSize()+"",
clientProfile.getActionSize()+"",
clientProfile.getActionGap()+""
clientProfile.getActionGap()+""
);
);
sendMessage(message);
sendMessage(message);
}
}
public void deleteProfile(String ID) throws SevereException
public void deleteProfile(String ID) throws SevereException
{
{
Message message = new Message("delete_profile");
Message message = new Message("delete_profile");
message.setStringValue(ID);
message.setStringValue(ID);
sendMessage(message);
sendMessage(message);
}
}
public void actionClicked(Message message)
public void actionClicked(Message message)
{
{
try
try
{
{
String[] r = message.getStringArrValue();
String[] r = message.getStringArrValue();
String profileID = r[0];
String profileID = r[0];
String actionID = r[1];
String actionID = r[1];
boolean toggle = r[2].equals("true");
boolean toggle = r[2].equals("true");
Action action = client.getProfileByID(profileID).getActionByID(actionID);
Action action = client.getProfileByID(profileID).getActionByID(actionID);
if(action.getActionType() == ActionType.NORMAL || action.getActionType() == ActionType.TOGGLE)
if(action.getActionType() == ActionType.NORMAL || action.getActionType() == ActionType.TOGGLE)
{
{
ExternalPlugin original = ExternalPlugins.getInstance().getPluginByModuleName(
ExternalPlugin original = ExternalPlugins.getInstance().getPluginByModuleName(
action.getModuleName()
action.getModuleName()
);
);
if(original == null)
if(original == null)
{
{
throw new MinorException(
throw new MinorException(
"The action isn't installed on the server."
"The action isn't installed on the server."
);
);
}
}
ExternalPlugin externalPlugin = original.clone();
ExternalPlugin externalPlugin = original.clone();
externalPlugin.setLocation(action.getLocation());
externalPlugin.setLocation(action.getLocation());
externalPlugin.setDisplayText(action.getDisplayText());
externalPlugin.setDisplayText(action.getDisplayText());
externalPlugin.setID(actionID);
externalPlugin.setID(actionID);
externalPlugin.setDelayBeforeExecuting(action.getDelayBeforeExecuting());
externalPlugin.setDelayBeforeExecuting(action.getDelayBeforeExecuting());
externalPlugin.setClientProperties(action.getClientProperties());
externalPlugin.setClientProperties(action.getClientProperties());
new Thread(new Task<Void>() {
new Thread(new Task<Void>() {
@Override
@Override
protected Void call()
protected Void call()
{
{
try
try
{
{
System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@2 "+externalPlugin.getDelayBeforeExecuting());
System.out.println("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@2 "+externalPlugin.getDelayBeforeExecuting());
Thread.sleep(externalPlugin.getDelayBeforeExecuting());
Thread.sleep(externalPlugin.getDelayBeforeExecuting());
if(externalPlugin instanceof ToggleAction)
if(externalPlugin instanceof ToggleAction)
{
{
boolean result = serverListener.onToggleActionClicked((ToggleAction) externalPlugin, toggle);
boolean result = serverListener.onToggleActionClicked((ToggleAction) externalPlugin, toggle);
if(!result)
if(!result)
{
{
sendActionFailed(profileID, actionID);
sendActionFailed(profileID, actionID);
}
}
}
}
else
else
{
{
boolean result = serverListener.onNormalActionClicked((NormalAction) externalPlugin);
boolean result = serverListener.onNormalActionClicked((NormalAction) externalPlugin);
if(!result)
if(!result)
{
{
sendActionFailed(profileID, actionID);
sendActionFailed(profileID, actionID);
}
}
}
}
}
}
catch (SevereException e)
catch (SevereException e)
{
{
exceptionAndAlertHandler.handleSevereException(e);
exceptionAndAlertHandler.handleSevereException(e);
}
}
catch (Exception e)
catch (Exception e)
{
{
e.printStackTrace();
e.printStackTrace();
}
}
return null;
return null;
}
}
}).start();
}).start();
}
}
} catch (Exception e) {
} catch (Exception e) {
e.printStackTrace();
e.printStackTrace();
exceptionAndAlertHandler.handleMinorException(new MinorException(e.getMessage()));
exceptionAndAlertHandler.handleMinorException(new MinorException(e.getMessage()));
}
}
}
}
public void sendActionFailed(String profileID, String actionID) throws SevereException {
public void sendActionFailed(String profileID, String actionID) throws SevereException {
logger.info("Sending failed status ...");
logger.info("Sending failed status ...");
Message message = new Message("action_failed");
Message message = new Message("action_failed");
message.setStringArrValue(profileID, actionID);
message.setStringArrValue(profileID, actionID);
sendMessage(message);
sendMessage(message);
}
}
}
}
package com.stream_pi.server.window.dashboard;
package com.stream_pi.server.window.dashboard;
import com.stream_pi.action_api.action.Action;
import com.stream_pi.action_api.action.Action;
import com.stream_pi.action_api.action.ActionType;
import com.stream_pi.action_api.action.ActionType;
import com.stream_pi.action_api.action.DisplayTextAlignment;
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.Property;
import com.stream_pi.action_api.actionproperty.property.Type;
import com.stream_pi.action_api.actionproperty.property.Type;
import com.stream_pi.action_api.normalaction.ExternalPlugin;
import com.stream_pi.action_api.normalaction.ExternalPlugin;
import com.stream_pi.action_api.normalaction.NormalAction;
import com.stream_pi.action_api.normalaction.NormalAction;
import com.stream_pi.action_api.otheractions.CombineAction;
import com.stream_pi.action_api.otheractions.CombineAction;
import com.stream_pi.action_api.otheractions.FolderAction;
import com.stream_pi.action_api.otheractions.FolderAction;
import com.stream_pi.server.action.ExternalPlugins;
import com.stream_pi.server.action.ExternalPlugins;
import com.stream_pi.util.uihelper.SpaceFiller;
import com.stream_pi.util.uihelper.SpaceFiller;
import javafx.application.HostServices;
import javafx.application.HostServices;
import javafx.geometry.Insets;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.geometry.Pos;
import javafx.scene.CacheHint;
import javafx.scene.CacheHint;
import javafx.scene.Node;
import javafx.scene.Node;
import javafx.scene.control.*;
import javafx.scene.control.*;
import javafx.scene.image.ImageView;
import javafx.scene.image.ImageView;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.ClipboardContent;
import javafx.scene.input.Dragboard;
import javafx.scene.input.Dragboard;
import javafx.scene.input.TransferMode;
import javafx.scene.input.TransferMode;
import javafx.scene.layout.*;
import javafx.scene.layout.*;
import org.kordamp.ikonli.javafx.FontIcon;
import org.kordamp.ikonli.javafx.FontIcon;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashMap;
public class PluginsPane extends VBox {
public class PluginsPane extends VBox {
private Button settingsButton;
private Button settingsButton;
public PluginsPane(HostServices hostServices)
public PluginsPane(HostServices hostServices)
{
{
setMinWidth(250);
setMinWidth(250);
setMaxWidth(350);
setMaxWidth(350);
getStyleClass().add("plugins_pane");
getStyleClass().add("plugins_pane");
setPadding(new Insets(10));
setPadding(new Insets(10));
this.hostServices = hostServices;
this.hostServices = hostServices;
initUI();
initUI();
}
}
private Accordion pluginsAccordion;
private Accordion pluginsAccordion;
public void initUI()
public void initUI()
{
{
pluginsAccordion = new Accordion();
pluginsAccordion = new Accordion();
pluginsAccordion.getStyleClass().add("plugins_pane_accordion");
pluginsAccordion.getStyleClass().add("plugins_pane_accordion");
pluginsAccordion.setCache(true);
pluginsAccordion.setCache(true);
settingsButton = new Button();
settingsButton = new Button();
settingsButton.getStyleClass().add("plugins_pane_settings_button");
settingsButton.getStyleClass().add("plugins_pane_settings_button");
FontIcon cog = new FontIcon("fas-cog");
FontIcon cog = new FontIcon("fas-cog");
settingsButton.setGraphic(cog);
settingsButton.setGraphic(cog);
HBox settingsHBox = new HBox(settingsButton);
HBox settingsHBox = new HBox(settingsButton);
settingsHBox.getStyleClass().add("plugins_pane_settings_button_parent");
settingsHBox.getStyleClass().add("plugins_pane_settings_button_parent");
settingsHBox.setAlignment(Pos.CENTER_RIGHT);
settingsHBox.setAlignment(Pos.CENTER_RIGHT);
Label pluginsLabel = new Label("Plugins");
Label pluginsLabel = new Label("Plugins");
pluginsLabel.getStyleClass().add("plugins_pane_top_label");
pluginsLabel.getStyleClass().add("plugins_pane_top_label");
getChildren().addAll(pluginsLabel, pluginsAccordion, SpaceFiller.vertical(), settingsHBox);
getChildren().addAll(pluginsLabel, pluginsAccordion, SpaceFiller.vertical(), settingsHBox);
}
}
public Button getSettingsButton()
public Button getSettingsButton()
{
{
return settingsButton;
return settingsButton;
}
}
public void clearData()
public void clearData()
{
{
pluginsAccordion.getPanes().clear();
pluginsAccordion.getPanes().clear();
}
}
public void loadData()
public void loadData()
{
{
HashMap<String, ArrayList<ExternalPlugin>> sortedPlugins = ExternalPlugins.getInstance().getSortedPlugins();
HashMap<String, ArrayList<ExternalPlugin>> sortedPlugins = ExternalPlugins.getInstance().getSortedPlugins();
for(String eachCategory : sortedPlugins.keySet())
for(String eachCategory : sortedPlugins.keySet())
{
{
VBox vBox = new VBox();
VBox vBox = new VBox();
vBox.getStyleClass().add("plugins_pane_each_plugin_box_parent");
vBox.getStyleClass().add("plugins_pane_each_plugin_box_parent");
TitledPane pane = new TitledPane(eachCategory, vBox);
TitledPane pane = new TitledPane(eachCategory, vBox);
pane.getStyleClass().add("plugins_pane_each_plugin_category_titled_pane");
pane.getStyleClass().add("plugins_pane_each_plugin_category_titled_pane");
for(ExternalPlugin eachAction : sortedPlugins.get(eachCategory))
for(ExternalPlugin eachAction : sortedPlugins.get(eachCategory))
{
{
if(!eachAction.isVisibleInPluginsPane())
if(!eachAction.isVisibleInPluginsPane())
continue;
continue;
Button eachNormalActionPluginButton = new Button();
Button eachNormalActionPluginButton = new Button();
eachNormalActionPluginButton.getStyleClass().add("plugins_pane_each_plugin_button");
eachNormalActionPluginButton.getStyleClass().add("plugins_pane_each_plugin_button");
HBox.setHgrow(eachNormalActionPluginButton, Priority.ALWAYS);
HBox.setHgrow(eachNormalActionPluginButton, Priority.ALWAYS);
eachNormalActionPluginButton.setMaxWidth(Double.MAX_VALUE);
eachNormalActionPluginButton.setMaxWidth(Double.MAX_VALUE);
eachNormalActionPluginButton.setAlignment(Pos.CENTER_LEFT);
eachNormalActionPluginButton.setAlignment(Pos.CENTER_LEFT);
Node graphic = eachAction.getServerButtonGraphic();
Node graphic = eachAction.getServerButtonGraphic();
if(graphic == null)
if(graphic == null)
{
{
FontIcon cogs = new FontIcon("fas-cogs");
FontIcon cogs = new FontIcon("fas-cogs");
cogs.getStyleClass().add("plugins_pane_each_plugin_button_icon");
cogs.getStyleClass().add("plugins_pane_each_plugin_button_icon");
eachNormalActionPluginButton.setGraphic(cogs);
eachNormalActionPluginButton.setGraphic(cogs);
}
}
else
else
{
{
if(graphic instanceof FontIcon)
if(graphic instanceof FontIcon)
{
{
FontIcon fi = (FontIcon) graphic;
FontIcon fi = (FontIcon) graphic;
fi.getStyleClass().add("plugins_pane_each_plugin_button_icon");
fi.getStyleClass().add("plugins_pane_each_plugin_button_icon");
eachNormalActionPluginButton.setGraphic(fi);
eachNormalActionPluginButton.setGraphic(fi);
}
}
else if(graphic instanceof ImageView)
else if(graphic instanceof ImageView)
{
{
ImageView iv = (ImageView) graphic;
ImageView iv = (ImageView) graphic;
iv.getStyleClass().add("plugins_pane_each_plugin_button_imageview");
iv.getStyleClass().add("plugins_pane_each_plugin_button_imageview");
iv.setPreserveRatio(false);
iv.setPreserveRatio(false);
eachNormalActionPluginButton.setGraphic(iv);
eachNormalActionPluginButton.setGraphic(iv);
}
}
}
}
eachNormalActionPluginButton.setText(eachAction.getName());
eachNormalActionPluginButton.setText(eachAction.getName());
eachNormalActionPluginButton.setOnDragDetected(mouseEvent -> {
eachNormalActionPluginButton.setOnDragDetected(mouseEvent -> {
Dragboard db = eachNormalActionPluginButton.startDragAndDrop(TransferMode.ANY);
Dragboard db = eachNormalActionPluginButton.startDragAndDrop(TransferMode.ANY);
ClipboardContent content = new ClipboardContent();
ClipboardContent content = new ClipboardContent();
content.put(Action.getDataFormat(), createFakeAction(eachAction, "Untitled action"));
content.put(Action.getDataFormat(), createFakeAction(eachAction, "Untitled action"));
db.setContent(content);
db.setContent(content);
mouseEvent.consume();
mouseEvent.consume();
});
});
HBox hBox = new HBox(eachNormalActionPluginButton);
HBox hBox = new HBox(eachNormalActionPluginButton);
hBox.getStyleClass().add("plugins_pane_each_plugin_box");
hBox.getStyleClass().add("plugins_pane_each_plugin_box");
hBox.setAlignment(Pos.TOP_LEFT);
hBox.setAlignment(Pos.TOP_LEFT);
HBox.setHgrow(eachNormalActionPluginButton, Priority.ALWAYS);
HBox.setHgrow(eachNormalActionPluginButton, Priority.ALWAYS);
if(eachAction.getHelpLink() != null) {
if(eachAction.getHelpLink() != null) {
Button helpButton = new Button();
Button helpButton = new Button();
helpButton.getStyleClass().add("plugins_pane_each_plugin_button_help_icon");
helpButton.getStyleClass().add("plugins_pane_each_plugin_button_help_icon");
FontIcon questionIcon = new FontIcon("fas-question");
FontIcon questionIcon = new FontIcon("fas-question");
questionIcon.getStyleClass().add("plugins_pane_each_plugin_button_help_button_icon");
questionIcon.getStyleClass().add("plugins_pane_each_plugin_button_help_button_icon");
helpButton.setGraphic(questionIcon);
helpButton.setGraphic(questionIcon);
helpButton.setOnAction(event -> hostServices.showDocument(eachAction.getHelpLink()));
helpButton.setOnAction(event -> hostServices.showDocument(eachAction.getHelpLink()));
hBox.getChildren().add(helpButton);
hBox.getChildren().add(helpButton);
}
}
vBox.getChildren().add(hBox);
vBox.getChildren().add(hBox);
}
}
if(vBox.getChildren().size() > 0)
if(vBox.getChildren().size() > 0)
pluginsAccordion.getPanes().add(pane);
pluginsAccordion.getPanes().add(pane);
}
}
}
}
private HostServices hostServices;
private HostServices hostServices;
public Action createFakeAction(Action action, String displayText)
public Action createFakeAction(Action action, String displayText)
{
{
Action newAction = new Action(action.getActionType());
Action newAction = new Action(action.getActionType());
if(action.getActionType() == ActionType.NORMAL)
if(action.getActionType() == ActionType.NORMAL || action.getActionType() == ActionType.TOGGLE)
{
{
newAction.setModuleName(action.getModuleName());
newAction.setModuleName(action.getModuleName());
newAction.setVersion(action.getVersion());
newAction.setVersion(action.getVersion());
newAction.setName(action.getName());
newAction.setName(action.getName());
}
}
newAction.setClientProperties(action.getClientProperties());
newAction.setClientProperties(action.getClientProperties());
for(Property property : newAction.getClientProperties().get())
for(Property property : newAction.getClientProperties().get())
{
{
if(property.getType() == Type.STRING || property.getType() == Type.INTEGER || property.getType() == Type.DOUBLE)
if(property.getType() == Type.STRING || property.getType() == Type.INTEGER || property.getType() == Type.DOUBLE)
property.setRawValue(property.getDefaultRawValue());
property.setRawValue(property.getDefaultRawValue());
}
}
// newAction.setLocation(location);
// newAction.setLocation(location);
newAction.setIDRandom();
newAction.setIDRandom();
newAction.setShowDisplayText(true);
newAction.setShowDisplayText(true);
newAction.setDisplayText(displayText);
newAction.setDisplayText(displayText);
newAction.setDisplayTextAlignment(DisplayTextAlignment.CENTER);
newAction.setDisplayTextAlignment(DisplayTextAlignment.CENTER);
//action.setParent(root);
//action.setParent(root);
newAction.setBgColourHex("");
newAction.setBgColourHex("");
newAction.setDisplayTextFontColourHex("");
newAction.setDisplayTextFontColourHex("");
return newAction;
return newAction;
}
}
public void loadOtherActions()
public void loadOtherActions()
{
{
VBox vBox = new VBox();
VBox vBox = new VBox();
vBox.getStyleClass().add("plugins_pane_each_plugin_box_parent");
vBox.getStyleClass().add("plugins_pane_each_plugin_box_parent");
Button folderActionButton = new Button("Folder");
Button folderActionButton = new Button("Folder");
folderActionButton.getStyleClass().add("plugins_pane_each_plugin_button");
folderActionButton.getStyleClass().add("plugins_pane_each_plugin_button");
folderActionButton.setMaxWidth(Double.MAX_VALUE);
folderActionButton.setMaxWidth(Double.MAX_VALUE);
folderActionButton.setAlignment(Pos.CENTER_LEFT);
folderActionButton.setAlignment(Pos.CENTER_LEFT);
FontIcon folder = new FontIcon("fas-folder");
FontIcon folder = new FontIcon("fas-folder");
folderActionButton.setGraphic(folder);
folderActionButton.setGraphic(folder);
folderActionButton.setOnDragDetected(mouseEvent -> {
folderActionButton.setOnDragDetected(mouseEvent -> {
Dragboard db = folderActionButton.startDragAndDrop(TransferMode.ANY);
Dragboard db = folderActionButton.startDragAndDrop(TransferMode.ANY);
ClipboardContent content = new ClipboardContent();
ClipboardContent content = new ClipboardContent();
content.put(Action.getDataFormat(), createFakeAction(new FolderAction(), "Untitled Folder"));
content.put(Action.getDataFormat(), createFakeAction(new FolderAction(), "Untitled Folder"));
db.setContent(content);
db.setContent(content);
mouseEvent.consume();
mouseEvent.consume();
});
});
Button combineActionButton = new Button("Combine");
Button combineActionButton = new Button("Combine");
combineActionButton.getStyleClass().add("plugins_pane_each_plugin_button");
combineActionButton.getStyleClass().add("plugins_pane_each_plugin_button");
combineActionButton.setMaxWidth(Double.MAX_VALUE);
combineActionButton.setMaxWidth(Double.MAX_VALUE);
combineActionButton.setAlignment(Pos.CENTER_LEFT);
combineActionButton.setAlignment(Pos.CENTER_LEFT);
FontIcon list = new FontIcon("fas-list");
FontIcon list = new FontIcon("fas-list");
combineActionButton.setGraphic(list);
combineActionButton.setGraphic(list);
combineActionButton.setOnDragDetected(mouseEvent -> {
combineActionButton.setOnDragDetected(mouseEvent -> {
Dragboard db = combineActionButton.startDragAndDrop(TransferMode.ANY);
Dragboard db = combineActionButton.startDragAndDrop(TransferMode.ANY);
ClipboardContent content = new ClipboardContent();
ClipboardContent content = new ClipboardContent();
content.put(Action.getDataFormat(), createFakeAction(new CombineAction(), "Untitled Combine"));
content.put(Action.getDataFormat(), createFakeAction(new CombineAction(), "Untitled Combine"));
db.setContent(content);
db.setContent(content);
mouseEvent.consume();
mouseEvent.consume();
});
});
HBox.setHgrow(folderActionButton, Priority.ALWAYS);
HBox.setHgrow(folderActionButton, Priority.ALWAYS);
HBox h1 = new HBox(folderActionButton);
HBox h1 = new HBox(folderActionButton);
h1.getStyleClass().add("plugins_pane_each_plugin_box");
h1.getStyleClass().add("plugins_pane_each_plugin_box");
HBox.setHgrow(combineActionButton, Priority.ALWAYS);
HBox.setHgrow(combineActionButton, Priority.ALWAYS);
HBox h2 = new HBox(combineActionButton);
HBox h2 = new HBox(combineActionButton);
h2.getStyleClass().add("plugins_pane_each_plugin_box");
h2.getStyleClass().add("plugins_pane_each_plugin_box");
vBox.getChildren().addAll(h1, h2);
vBox.getChildren().addAll(h1, h2);
TitledPane pane = new TitledPane("Stream-Pi", vBox);
TitledPane pane = new TitledPane("Stream-Pi", vBox);
pane.getStyleClass().add("plugins_pane_each_plugin_category_titled_pane");
pane.getStyleClass().add("plugins_pane_each_plugin_category_titled_pane");
pluginsAccordion.getPanes().add(pane);
pluginsAccordion.getPanes().add(pane);
pluginsAccordion.setCache(true);
pluginsAccordion.setCache(true);
pluginsAccordion.setCacheHint(CacheHint.SPEED);
pluginsAccordion.setCacheHint(CacheHint.SPEED);
}
}
}
}
package com.stream_pi.server.window.dashboard.actiondetailpane;
package com.stream_pi.server.window.dashboard.actiondetailpane;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.List;
import java.util.List;
import java.util.logging.Logger;
import java.util.logging.Logger;
import com.stream_pi.action_api.action.Action;
import com.stream_pi.action_api.action.Action;
import com.stream_pi.action_api.action.ActionType;
import com.stream_pi.action_api.action.ActionType;
import com.stream_pi.action_api.action.DisplayTextAlignment;
import com.stream_pi.action_api.action.DisplayTextAlignment;
import com.stream_pi.action_api.actionproperty.ClientProperties;
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.Property;
import com.stream_pi.action_api.actionproperty.property.Type;
import com.stream_pi.action_api.actionproperty.property.Type;
import com.stream_pi.server.client.ClientProfile;
import com.stream_pi.server.client.ClientProfile;
import com.stream_pi.server.connection.ClientConnection;
import com.stream_pi.server.connection.ClientConnection;
import com.stream_pi.server.uipropertybox.UIPropertyBox;
import com.stream_pi.server.uipropertybox.UIPropertyBox;
import com.stream_pi.server.window.ExceptionAndAlertHandler;
import com.stream_pi.server.window.ExceptionAndAlertHandler;
import com.stream_pi.server.window.dashboard.actiongridpane.ActionBox;
import com.stream_pi.server.window.dashboard.actiongridpane.ActionBox;
import com.stream_pi.util.exception.SevereException;
import com.stream_pi.util.exception.SevereException;
import javafx.application.Platform;
import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.concurrent.Task;
import javafx.scene.control.Button;
import javafx.scene.control.Button;
public class OnSaveActionTask extends Task<Void>
public class OnSaveActionTask extends Task<Void>
{
{
private Logger logger;
private Logger logger;
public OnSaveActionTask(ClientConnection connection, Action action, String delayBeforeRunningString, String displayNameText, boolean isCombineChild,
public OnSaveActionTask(ClientConnection connection, Action action, String delayBeforeRunningString, String displayNameText, boolean isCombineChild,
boolean isShowDisplayText, boolean isDefaultDisplayTextColour, String displayTextFontColour, boolean isClearIcon,
boolean isShowDisplayText, boolean isDefaultDisplayTextColour, String displayTextFontColour, boolean isClearIcon,
boolean isHideDefaultIcon, boolean isHideToggleOffIcon, boolean isHideToggleOnIcon, DisplayTextAlignment displayTextAlignment, boolean isTransparentBackground, String backgroundColour,
boolean isHideDefaultIcon, boolean isHideToggleOffIcon, boolean isHideToggleOnIcon, DisplayTextAlignment displayTextAlignment, boolean isTransparentBackground, String backgroundColour,
CombineActionPropertiesPane combineActionPropertiesPane, ClientProfile clientProfile, boolean sendIcon, ActionBox actionBox,
CombineActionPropertiesPane combineActionPropertiesPane, ClientProfile clientProfile, boolean sendIcon, ActionBox actionBox,
ArrayList<UIPropertyBox> actionClientProperties, ExceptionAndAlertHandler exceptionAndAlertHandler, Button saveButton, Button deleteButton,
ArrayList<UIPropertyBox> actionClientProperties, ExceptionAndAlertHandler exceptionAndAlertHandler, Button saveButton, Button deleteButton,
boolean runAsync)
boolean runAsync)
{
{
this.saveButton = saveButton;
this.saveButton = saveButton;
this.deleteButton = deleteButton;
this.deleteButton = deleteButton;
this.delayBeforeRunningString = delayBeforeRunningString;
this.delayBeforeRunningString = delayBeforeRunningString;
this.connection = connection;
this.connection = connection;
this.action = action;
this.action = action;
this.displayNameText = displayNameText;
this.displayNameText = displayNameText;
this.isCombineChild = isCombineChild;
this.isCombineChild = isCombineChild;
this.isShowDisplayText = isShowDisplayText;
this.isShowDisplayText = isShowDisplayText;
this.isDefaultDisplayTextColour = isDefaultDisplayTextColour;
this.isDefaultDisplayTextColour = isDefaultDisplayTextColour;
this.displayTextFontColour = displayTextFontColour;
this.displayTextFontColour = displayTextFontColour;
this.isClearIcon = isClearIcon;
this.isClearIcon = isClearIcon;
this.isHideDefaultIcon = isHideDefaultIcon;
this.isHideDefaultIcon = isHideDefaultIcon;
this.isHideToggleOffIcon = isHideToggleOffIcon;
this.isHideToggleOffIcon = isHideToggleOffIcon;
this.isHideToggleOnIcon = isHideToggleOnIcon;
this.isHideToggleOnIcon = isHideToggleOnIcon;
this.displayTextAlignment = displayTextAlignment;
this.displayTextAlignment = displayTextAlignment;
this.isTransparentBackground = isTransparentBackground;
this.isTransparentBackground = isTransparentBackground;
this.combineActionPropertiesPane = combineActionPropertiesPane;
this.combineActionPropertiesPane = combineActionPropertiesPane;
this.clientProfile = clientProfile;
this.clientProfile = clientProfile;
this.sendIcon = sendIcon;
this.sendIcon = sendIcon;
this.actionBox = actionBox;
this.actionBox = actionBox;
this.exceptionAndAlertHandler = exceptionAndAlertHandler;
this.exceptionAndAlertHandler = exceptionAndAlertHandler;
this.backgroundColour = backgroundColour;
this.backgroundColour = backgroundColour;
this.actionClientProperties = actionClientProperties;
this.actionClientProperties = actionClientProperties;
logger = Logger.getLogger(getClass().getName());
logger = Logger.getLogger(getClass().getName());
if(runAsync)
if(runAsync)
new Thread(this).start();
new Thread(this).start();
else
else
runTask();
runTask();
}
}
private Button saveButton;
private Button saveButton;
private Button deleteButton;
private Button deleteButton;
private String delayBeforeRunningString;
private String delayBeforeRunningString;
private boolean isShowDisplayText;
private boolean isShowDisplayText;
private boolean isCombineChild;
private boolean isCombineChild;
private String displayNameText;
private String displayNameText;
private boolean isDefaultDisplayTextColour;
private boolean isDefaultDisplayTextColour;
private ArrayList<UIPropertyBox> actionClientProperties;
private ArrayList<UIPropertyBox> actionClientProperties;
private String displayTextFontColour;
private String displayTextFontColour;
private boolean isClearIcon;
private boolean isClearIcon;
private boolean isHideDefaultIcon;
private boolean isHideDefaultIcon;
private boolean isHideToggleOffIcon;
private boolean isHideToggleOffIcon;
private boolean isHideToggleOnIcon;
private boolean isHideToggleOnIcon;
private DisplayTextAlignment displayTextAlignment;
private DisplayTextAlignment displayTextAlignment;
private boolean isTransparentBackground;
private boolean isTransparentBackground;
private String backgroundColour;
private String backgroundColour;
private CombineActionPropertiesPane combineActionPropertiesPane;
private CombineActionPropertiesPane combineActionPropertiesPane;
private ClientProfile clientProfile;
private ClientProfile clientProfile;
private boolean sendIcon;
private boolean sendIcon;
private ActionBox actionBox;
private ActionBox actionBox;
private ExceptionAndAlertHandler exceptionAndAlertHandler;
private ExceptionAndAlertHandler exceptionAndAlertHandler;
private Action action;
private Action action;
private ClientConnection connection;
private ClientConnection connection;
private void setSaveDeleteButtonState(boolean state)
private void setSaveDeleteButtonState(boolean state)
{
{
Platform.runLater(()->{
Platform.runLater(()->{
saveButton.setDisable(state);
saveButton.setDisable(state);
deleteButton.setDisable(state);
deleteButton.setDisable(state);
});
});
}
}
private void runTask()
private void runTask()
{
{
action.setDisplayText(displayNameText);
action.setDisplayText(displayNameText);
if(!isCombineChild)
if(!isCombineChild)
{
{
setSaveDeleteButtonState(true);
setSaveDeleteButtonState(true);
action.setShowDisplayText(isShowDisplayText);
action.setShowDisplayText(isShowDisplayText);
if(isDefaultDisplayTextColour)
if(isDefaultDisplayTextColour)
action.setDisplayTextFontColourHex("");
action.setDisplayTextFontColourHex("");
else
else
{
{
action.setDisplayTextFontColourHex(displayTextFontColour);
action.setDisplayTextFontColourHex(displayTextFontColour);
//String fontColour = "#" + displayTextColourPicker.getValue().toString().substring(2);
//String fontColour = "#" + displayTextColourPicker.getValue().toString().substring(2);
//action.setDisplayTextFontColourHex(fontColour);
//action.setDisplayTextFontColourHex(fontColour);
}
}
if(isClearIcon)
if(isClearIcon)
{
{
action.setIcons(null);
action.setIcons(null);
action.setCurrentIconState("");
action.setCurrentIconState("");
}
}
if(action.getActionType() == ActionType.NORMAL)
if(action.getActionType() == ActionType.NORMAL)
{
{
if(isHideDefaultIcon)
if(isHideDefaultIcon)
{
{
action.setCurrentIconState("default");
if(action.getIcon("default") != null)
action.setCurrentIconState("default");
}
}
else
else
{
{
action.setCurrentIconState("");
action.setCurrentIconState("");
}
}
}
}
else if (action.getActionType() == ActionType.TOGGLE)
else if (action.getActionType() == ActionType.TOGGLE)
{
{
action.setCurrentIconState(isHideToggleOffIcon+"__"+isHideToggleOnIcon);
action.setCurrentIconState(isHideToggleOffIcon+"__"+isHideToggleOnIcon);
}
}
action.setDisplayTextAlignment(displayTextAlignment);
action.setDisplayTextAlignment(displayTextAlignment);
if(isTransparentBackground)
if(isTransparentBackground)
action.setBgColourHex("");
action.setBgColourHex("");
else
else
{
{
action.setBgColourHex(backgroundColour);
action.setBgColourHex(backgroundColour);
}
}
}
}
System.out.println("parent : "+action.getParent());
System.out.println("parent : "+action.getParent());
if(action.getActionType() == ActionType.COMBINE)
if(action.getActionType() == ActionType.COMBINE)
{
{
List<String> finalChildren = combineActionPropertiesPane.getFinalChildren();
List<String> finalChildren = combineActionPropertiesPane.getFinalChildren();
System.out.println("2334 "+finalChildren.size());
System.out.println("2334 "+finalChildren.size());
ClientProperties clientProperties = new ClientProperties();
ClientProperties clientProperties = new ClientProperties();
for(int i = 0;i<finalChildren.size();i++)
for(int i = 0;i<finalChildren.size();i++)
{
{
Property property = new Property(i+"", Type.STRING);
Property property = new Property(i+"", Type.STRING);
property.setRawValue(finalChildren.get(i));
property.setRawValue(finalChildren.get(i));
clientProperties.addProperty(property);
clientProperties.addProperty(property);
}
}
action.getClientProperties().set(clientProperties);
action.getClientProperties().set(clientProperties);
}
}
else
else
{
{
action.setDelayBeforeExecuting(Integer.parseInt(delayBeforeRunningString));
action.setDelayBeforeExecuting(Integer.parseInt(delayBeforeRunningString));
//properties
//properties
for (UIPropertyBox clientProperty : actionClientProperties) {
for (UIPropertyBox clientProperty : actionClientProperties) {
action.getClientProperties().get().get(clientProperty.getIndex()).setRawValue(clientProperty.getRawValue());
action.getClientProperties().get().get(clientProperty.getIndex()).setRawValue(clientProperty.getRawValue());
}
}
}
}
try
try
{
{
logger.info("Saving action ... "+action.isHasIcon()+"+"+sendIcon);
logger.info("Saving action ... "+action.isHasIcon()+"+"+sendIcon);
connection.saveActionDetails(clientProfile.getID(), action);
connection.saveActionDetails(clientProfile.getID(), action);
if(sendIcon)
if(sendIcon)
{
{
sendAllIcons(clientProfile, action);
sendAllIcons(clientProfile, action);
}
}
if(!isCombineChild)
if(!isCombineChild)
{
{
Platform.runLater(()->{
Platform.runLater(()->{
actionBox.clear();
actionBox.clear();
actionBox.setAction(action);
actionBox.setAction(action);
//actionBox.baseInit();
//actionBox.baseInit();
actionBox.init();
actionBox.init();
});
});
setSaveDeleteButtonState(false);
setSaveDeleteButtonState(false);
}
}
clientProfile.removeActionByID(action.getID());
clientProfile.removeActionByID(action.getID());
clientProfile.addAction(action);
clientProfile.addAction(action);
}
}
catch (SevereException e)
catch (SevereException e)
{
{
e.printStackTrace();
e.printStackTrace();
exceptionAndAlertHandler.handleSevereException(e);
exceptionAndAlertHandler.handleSevereException(e);
}
}
catch (CloneNotSupportedException e)
catch (CloneNotSupportedException e)
{
{
e.printStackTrace();
e.printStackTrace();
}
}
}
}
private void sendAllIcons(ClientProfile clientProfile, Action action) throws SevereException
private void sendAllIcons(ClientProfile clientProfile, Action action) throws SevereException
{
{
for(String state : action.getIcons().keySet())
for(String state : action.getIcons().keySet())
{
{
connection.sendIcon(clientProfile.getID(), action.getID(), state, action.getIcon(state));
connection.sendIcon(clientProfile.getID(), action.getID(), state, action.getIcon(state));
}
}
}
}
@Override
@Override
protected Void call() throws Exception
protected Void call() throws Exception
{
{
runTask();
runTask();
return null;
return null;
}
}
}
}
module com.stream_pi.server {
module com.stream_pi.server {
uses com.stream_pi.action_api.action.Action;
uses com.stream_pi.action_api.action.Action;
uses com.stream_pi.action_api.normalaction.NormalAction;
uses com.stream_pi.action_api.normalaction.NormalAction;
uses com.stream_pi.action_api.normalaction.ExternalPlugin;
requires com.stream_pi.action_api;
requires com.stream_pi.action_api;
requires com.stream_pi.util;
requires com.stream_pi.util;
requires com.stream_pi.theme_api;
requires com.stream_pi.theme_api;
requires org.kordamp.ikonli.javafx;
requires org.kordamp.ikonli.javafx;
requires java.xml;
requires java.xml;
requires javafx.base;
requires javafx.base;
requires javafx.graphics;
requires javafx.graphics;
requires javafx.controls;
requires javafx.controls;
requires javafx.media;
requires javafx.media;
requires java.desktop;
requires java.desktop;
requires java.sql;
requires java.sql;
exports com.stream_pi.server;
exports com.stream_pi.server;
}
}