From f6ae688d1eb33feb2ca0b77dd2f905da4221268c Mon Sep 17 00:00:00 2001 From: Ludovic Apvrille <ludovic.apvrille@telecom-paristech.fr> Date: Fri, 12 Jun 2020 13:26:22 +0200 Subject: [PATCH] Update on plugins: doc and co. Still to implement: custom commands --- .../ttool_development_infrastructure.tex | 61 +++- .../CustomizerGraphicalComponent.java | 79 ++++- src/main/java/cli/Interpreter.java | 2 +- src/main/java/cli/PluginAction.java | 278 ++++++++++++++++++ src/main/java/myutil/Plugin.java | 81 ++++- src/main/java/myutil/PluginManager.java | 3 +- 6 files changed, 482 insertions(+), 22 deletions(-) create mode 100644 src/main/java/cli/PluginAction.java diff --git a/doc/dev_infrastructure/ttool_development_infrastructure.tex b/doc/dev_infrastructure/ttool_development_infrastructure.tex index a4520677c8..9ee2edc1a9 100644 --- a/doc/dev_infrastructure/ttool_development_infrastructure.tex +++ b/doc/dev_infrastructure/ttool_development_infrastructure.tex @@ -1581,6 +1581,65 @@ if (instance == null) { \subsection{Using plugins from the command line interface} -Under development. +\subsubsection{Main commands} +\begin{itemize} +\item \textit{plugin load <path> <plugin name> [optional: plugin package]}: loads a plugin +\begin{verbatim} +$ cd TTool/bin +$ java -jar ttool-cli.jar -interact +0> plugin list +plugin list +No plugins +1> plugin load ../plugins CustomizerGraphicalComponent.jar +plugin load ../plugins CustomizerGraphicalComponent.jar +2> plugin list +plugin list +CustomizerGraphicalComponent.jar +\end{verbatim} +\item \textit{plugin info <plugin name>}: provides information on a given plugin +\begin{verbatim} +\item \textit{plugin list}: list all the loaded plugins +\begin{verbatim} +$ plugin list +CustomizerAvatarJavaCodeGeneration.jar +CustomizerGraphicalComponent.jar +\end{verbatim} +\item \textit{plugin info <plugin name>}: provides information on a given plugin +\begin{verbatim} +$ plugin info CustomizerGraphicalComponent.jar +Package: +Path: ../plugins +Has graphical component? false +Has Avatar code generator? true +Has Diplodocus code generator? false +Custom commands: getPanelClassName getWidth getHeight setDefaultWidth +\end{verbatim} +\end{itemize} +\item \textit{plugin info-command <plugin name> <command name>}: provides information on a given command provided by a plugin +\begin{verbatim} +$ plugin info-command CustomizerGraphicalComponent.jar setDefaultWidth +static void setDefaultWidth(int defaultWidth): makes it possible to set the default width +\end{verbatim} +\end{itemize} + +\subsubsection{Mandatory functions} +A plugin that may be used by the command line interface must define the following methods: +\begin{itemize} +\item \textit{public static String hasCommandLineInterface()}: returns the class of the plugin implementing custom commands +\item \textit{public static String getCommandsOfCommandLineInterface()}: returns all the names of custom commands (for instance: "getValue") +\item \textit{public static String getHelpOnCommandLineInterfaceFunction(String command)}: returns some help about the function given as parameter. +\end{itemize} + + +\subsubsection{Custom commands} +A plugin can define a list of custom commands. These commands can take only \textit{String} as parameter and can return either nothing or a String. They have to be implemented with a method having the same name as the command. The method must also be \textbf{static}. + +For instance: +\begin{verbatim} +public static String getWidthS() { + return "100"; +} +\end{verbatim} + \end{document} diff --git a/plugins/testPluginGraphicalComponent/CustomizerGraphicalComponent.java b/plugins/testPluginGraphicalComponent/CustomizerGraphicalComponent.java index dbec671d78..f64f728563 100644 --- a/plugins/testPluginGraphicalComponent/CustomizerGraphicalComponent.java +++ b/plugins/testPluginGraphicalComponent/CustomizerGraphicalComponent.java @@ -38,16 +38,36 @@ * /** * Class CustomizerAvatarJavaCodeGeneration * Creation: 27/06/2017 - * @version 1.0 27/06/2017 + * @version 1.1 12/06/2020 * @author Ludovic APVRILLE * @see */ + import java.awt.*; import java.net.URL; import javax.swing.*; public class CustomizerGraphicalComponent { + private final static String[] CLI_COMMANDS = {"getPanelClassName", + "getWidthS", + "getHeightS", + "setDefaultWidth"}; + private final static String[] CLI_PROTOTYPES = {"getPanelClassName: returns a String", + "getWidthS: returns a String", + "getHeightS: returns a String", + "setDefaultWidth <int defaultWidth>: returns void"}; + + private final static String[] CLI_HELP_COMMANDS = { + "returns the associated panel name of the component", + "returns the default width", + "returns the default height", + "makes it possible to set the default width" + }; + + private static int DEFAULT_WIDTH = 100; + + public static ImageIcon myIcon; public CustomizerGraphicalComponent() { @@ -58,6 +78,32 @@ public class CustomizerGraphicalComponent { return "CustomizerGraphicalComponent"; } + public static String hasCommandLineInterface() { + return "CustomizerGraphicalComponent"; + } + + public static String getCommandsOfCommandLineInterface() { + StringBuffer sb = new StringBuffer(""); + for(String s: CLI_COMMANDS) { + sb.append(s + " " ); + } + return sb.toString(); + } + + public static String getHelpOnCommandLineInterfaceFunction(String command) { + int cpt = 0; + + command = command.toLowerCase(); + for(String s: CLI_COMMANDS) { + if (s.toLowerCase().compareTo(command) == 0) { + return CLI_PROTOTYPES[cpt] + ": " + CLI_HELP_COMMANDS[cpt]; + } + cpt ++; + } + return null; + + } + public static String getPanelClassName() { return "TMLArchiDiagramPanel"; } @@ -88,6 +134,15 @@ public class CustomizerGraphicalComponent { return "Plugin component"; } + + public static String getWidthS() { + return "100"; + } + + public static String getHeightS() { + return "50"; + } + public static int getWidth() { return 100; } @@ -96,6 +151,10 @@ public class CustomizerGraphicalComponent { return 50; } + public static void setDefaultWidth(int defaultWith) { + DEFAULT_WIDTH = defaultWith; + } + public boolean isMoveable() { return true; @@ -119,8 +178,8 @@ public class CustomizerGraphicalComponent { public int getWidth(Graphics g, String _value) { - int w = g.getFontMetrics ().stringWidth (_value); - return w + 20; + int w = g.getFontMetrics ().stringWidth (_value); + return w + 20; } public int getHeight(Graphics g, String _value) { @@ -128,23 +187,23 @@ public class CustomizerGraphicalComponent { } public void internalDrawing(Graphics g, int _x, int _y, int _width, int _height, String _value, String _diagramName) { - g.drawRect(_x, _y, _width, _height); - g.drawString(_value, _x+5, _y+20); + g.drawRect(_x, _y, _width, _height); + g.drawString(_value, _x+5, _y+20); } public boolean isOnMe(int _x, int _y, int _width, int _height, int _xP, int _yP) { - if ((_xP>_x) && (_xP<_x+_width) && (_yP>_y) && (_yP<_y+_height)) { - return true; - } + if ((_xP>_x) && (_xP<_x+_width) && (_yP>_y) && (_yP<_y+_height)) { + return true; + } return false; } public String editOnDoubleClick(JFrame _frame, String _value) { - String s = (String)JOptionPane.showInputDialog(_frame, "My plugin component name", + String s = (String)JOptionPane.showInputDialog(_frame, "My plugin component name", "setting value", JOptionPane.PLAIN_MESSAGE, myIcon, null, _value); - return s; + return s; } public static void main(String[] args) { diff --git a/src/main/java/cli/Interpreter.java b/src/main/java/cli/Interpreter.java index b5f027076f..991d47d615 100644 --- a/src/main/java/cli/Interpreter.java +++ b/src/main/java/cli/Interpreter.java @@ -58,7 +58,7 @@ import java.util.Vector; */ public class Interpreter implements Runnable, TerminalProviderInterface { - public final static Command[] commands = {new Action(), new Help(), new History(), new Print(), new Quit(), + public final static Command[] commands = {new Action(), new Help(), new History(), new Print(), new PluginAction(), new Quit(), new TestSpecific(), new TML(), new Set(), new Wait(), new Robot(), new BF(), new SimulatorScript()}; // Errors diff --git a/src/main/java/cli/PluginAction.java b/src/main/java/cli/PluginAction.java new file mode 100644 index 0000000000..e4c960ea98 --- /dev/null +++ b/src/main/java/cli/PluginAction.java @@ -0,0 +1,278 @@ +/* Copyright or (C) or Copr. GET / ENST, Telecom-Paris, Ludovic Apvrille + * + * ludovic.apvrille AT enst.fr + * + * This software is a computer program whose purpose is to allow the + * edition of TURTLE analysis, design and deployment diagrams, to + * allow the generation of RT-LOTOS or Java code from this diagram, + * and at last to allow the analysis of formal validation traces + * obtained from external tools, e.g. RTL from LAAS-CNRS and CADP + * from INRIA Rhone-Alpes. + * + * This software is governed by the CeCILL license under French law and + * abiding by the rules of distribution of free software. You can use, + * modify and/ or redistribute the software under the terms of the CeCILL + * license as circulated by CEA, CNRS and INRIA at the following URL + * "http://www.cecill.info". + * + * As a counterpart to the access to the source code and rights to copy, + * modify and redistribute granted by the license, users are provided only + * with a limited warranty and the software's author, the holder of the + * economic rights, and the successive licensors have only limited + * liability. + * + * In this respect, the user's attention is drawn to the risks associated + * with loading, using, modifying and/or developing or reproducing the + * software by the user in light of its specific status of free software, + * that may mean that it is complicated to manipulate, and that also + * therefore means that it is reserved for developers and experienced + * professionals having in-depth computer knowledge. Users are therefore + * encouraged to load and test the software's suitability as regards their + * requirements in conditions enabling the security of their systems and/or + * data to be ensured and, more generally, to use and operate it in the + * same conditions as regards security. + * + * The fact that you are presently reading this means that you have had + * knowledge of the CeCILL license and that you accept its terms. + */ + + +package cli; + +import avatartranslator.AvatarSpecification; +import avatartranslator.modelchecker.AvatarModelChecker; +import avatartranslator.modelcheckervalidator.ModelCheckerValidator; +import common.ConfigurationTTool; +import common.SpecConfigTTool; +import graph.RG; +import launcher.RTLLauncher; +import myutil.*; +import tmltranslator.TMLMapping; +import tmltranslator.TMLModeling; +import ui.MainGUI; +import ui.util.IconManager; +import ui.window.JDialogSystemCGeneration; +import ui.*; +import java.awt.*; +import java.io.File; +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.List; + + +/** + * Class PluginAction + * Creation: 12/06/2020 + * Version 2.0 12/06/2020 + * + * @author Ludovic APVRILLE + */ +public class PluginAction extends Command { + // Action commands + private final static String LIST_PLUGIN = "list"; + private final static String INFO_PLUGIN = "info"; + private final static String INFO_COMMAND_PLUGIN = "info-command"; + private final static String LOAD_PLUGIN = "load"; + + + + public PluginAction() { + + } + + public List<Command> getListOfSubCommands() { + return subcommands; + } + + public String getCommand() { + return "plugin"; + } + + public String getShortCommand() { + return "pl"; + } + + public String getUsage() { + return "action <subcommand> <options>"; + } + + public String getDescription() { + return "Can be used to performe actions with pluginsT"; + } + + + + + public void fillSubCommands() { + // List + Command list = new Command() { + public String getCommand() { + return LIST_PLUGIN; + } + + public String getShortCommand() { + return "li"; + } + + public String getDescription() { + return "List loaded plugins"; + } + + public String executeCommand(String command, Interpreter interpreter) { + if (PluginManager.pluginManager == null) { + System.out.println("No plugins"); + return null; + } + + StringBuffer sb = new StringBuffer(""); + for(Plugin p: PluginManager.pluginManager.plugins) { + sb.append(p.getName() + "\n"); + } + System.out.println(sb.toString()); + + return null; + } + }; + + // info + Command info = new Command() { + public String getCommand() { + return INFO_PLUGIN; + } + + public String getShortCommand() { + return "i"; + } + + public String getDescription() { + return "Get information on a given plugin"; + } + + public String executeCommand(String command, Interpreter interpreter) { + if (PluginManager.pluginManager == null) { + return "No plugins"; + } + + String[] commands = command.split(" "); + if (commands.length < 1) { + return Interpreter.BAD; + } + + System.out.println("Info on plugin:" + commands[0]); + Plugin p = PluginManager.pluginManager.getPlugin(commands[0]); + if (p == null) { + return "Unknown plugin " + commands[0]; + } + StringBuffer sb = new StringBuffer(""); + sb.append("Package:\t" + p.getPackageName() + "\n"); + sb.append("Path:\t" + p.getPath() + "\n"); + sb.append("Has graphical component?\t"); + if (p.hasGraphicalComponent()) { sb.append("true\n");} else {sb.append("false\n");} + sb.append("Has Avatar code generator?\t"); + if (p.hasAvatarCodeGenerator()) { sb.append("true\n");} else {sb.append("false\n");} + sb.append("Has Diplodocus code generator?\t"); + if (p.hasDiplodocusCodeGenerator()) { sb.append("true\n");} else {sb.append("false\n");} + sb.append("Has Command line interface?\t"); + if (p.hasCommandLineInterface()) { + sb.append("true\n"); + sb.append("Custom commands: " + p.getCommandLineInterfaceFunctions()); + } else {sb.append("false\n");} + + + System.out.println(sb.toString()); + + return null; + } + }; + + + // info on command + Command infoCommand = new Command() { + public String getCommand() { + return INFO_COMMAND_PLUGIN; + } + + public String getShortCommand() { + return "ic"; + } + + public String getDescription() { + return "Get information on a given command of a plugin"; + } + + public String executeCommand(String command, Interpreter interpreter) { + if (PluginManager.pluginManager == null) { + return "No plugins"; + } + + String[] commands = command.split(" "); + if (commands.length < 2) { + return Interpreter.BAD; + } + + Plugin p = PluginManager.pluginManager.getPlugin(commands[0]); + if (p == null) { + return "No such plugin"; + } + + String s = p.getHelpOnCommandLineInterfaceFunction(commands[1]); + + if ((s == null) || (s.length() == 0)) { + return "No such function"; + } + + System.out.println(s); + + return null; + } + }; + + // load + Command load = new Command() { + public String getCommand() { + return LOAD_PLUGIN; + } + + public String getShortCommand() { + return "lo"; + } + + public String getDescription() { + return "Load a new plugin. pl l <plugin path> <plugin name> <plugin package>"; + } + + public String executeCommand(String command, Interpreter interpreter) { + if (PluginManager.pluginManager == null) { + PluginManager.pluginManager = new PluginManager(); + } + + String[] commands = command.split(" "); + if (commands.length < 2) { + return Interpreter.BAD; + } + + String []names = new String[1]; + names[0] = commands[1]; + String []packages = new String[1]; + if (commands.length == 3) { + packages[0] = commands[2]; + } else { + packages[0] = ""; + } + + PluginManager.pluginManager.preparePlugins(commands[0], names, packages); + + return null; + } + }; + + + addAndSortSubcommand(list); + addAndSortSubcommand(info); + addAndSortSubcommand(infoCommand); + addAndSortSubcommand(load); + + } + +} diff --git a/src/main/java/myutil/Plugin.java b/src/main/java/myutil/Plugin.java index b4af971882..206af642db 100644 --- a/src/main/java/myutil/Plugin.java +++ b/src/main/java/myutil/Plugin.java @@ -62,6 +62,7 @@ public class Plugin { private Class classAvatarCodeGenerator; private Class classDiplodocusCodeGenerator; private Class classGraphicalComponent; + private Class classCommandLineInterface; public Plugin(String _path, String _name, String _packageName) { @@ -75,17 +76,27 @@ public class Plugin { return name; } + public String getPackageName() { + return packageName; + } + public String getPath() { return path; } public boolean hasAvatarCodeGenerator() { - String ret = executeRetStringMethod(removeJar(name), "hasAvatarCodeGenerator"); - if (ret != null) { - classAvatarCodeGenerator = getClass(ret); - return true; + String ret = null; + try { + ret = executeRetStringMethod(removeJar(name), "hasAvatarCodeGenerator"); + if (ret != null) { + classAvatarCodeGenerator = getClass(ret); + return true; + } + } catch(Exception e) { + return false; } + return false; } @@ -104,6 +115,41 @@ public class Plugin { return desc; } + public boolean hasCommandLineInterface() { + String ret = executeRetStringMethod(removeJar(name), "hasCommandLineInterface"); + if (ret != null) { + classCommandLineInterface = getClass(ret); + return true; + } + + return false; + } + + public String getCommandLineInterfaceFunctions() { + String ret = executeRetStringMethod(removeJar(name), "getCommandsOfCommandLineInterface"); + if (ret != null) { + return ret; + } + + return ""; + } + + public String getHelpOnCommandLineInterfaceFunction(String command) { + if (classCommandLineInterface == null) { + hasCommandLineInterface(); + } + if (classCommandLineInterface == null) { + return ""; + } + + String ret = executeStaticRetStringOneStringMethod(classCommandLineInterface,"getHelpOnCommandLineInterfaceFunction", command); + if (ret != null) { + return ret; + } + + return ""; + } + public ImageIcon getDiplodocusCodeGeneratorLogo() { String mName = "getLogoImage"; //TraceManager.addDev("Getting image with method=" + mName); @@ -222,7 +268,7 @@ public class Plugin { return c.getMethod(_methodName); } catch (Exception e) { - e.printStackTrace( System.out ); + //e.printStackTrace( System.out ); TraceManager.addDev("Exception when using plugin " + name + " with className=" + _className + " and method " + _methodName); return null; } @@ -231,11 +277,11 @@ public class Plugin { public String executeRetStringMethod(String _className, String _methodName) { // We have a valid plugin. We now need to get the Method - //TraceManager.addDev("-------- Getting " + _methodName + " of class " + _className); + TraceManager.addDev("-------- Getting " + _methodName + " of class " + _className); Method m = getMethod(_className, _methodName); - //TraceManager.addDev("-------- Got " + _methodName + " of class " + _className); + TraceManager.addDev("-------- Got " + _methodName + " of class " + _className); if (m == null) { - //TraceManager.addDev("Null method with class as a string class=" + _className + " _method=" + _methodName); + TraceManager.addDev("Null method with class as a string class=" + _className + " _method=" + _methodName); return null; } @@ -296,6 +342,25 @@ public class Plugin { method.invoke(instance, value); } + public static String executeStaticRetStringOneStringMethod(Class<?> c, String _methodName, String value) { + try { + Class[] cArg = new Class[1]; + cArg[0] = String.class; + //TraceManager.addDev("Getting <" + _methodName + "> in class <" + c.getName() + ">"); + Method m = c.getMethod(_methodName, cArg); + + if (m == null) { + TraceManager.addDev("Null method in executeRetStringMethod with Class parameter"); + return null; + } + return (String) (m.invoke(null, value)); + } catch (Exception e) { + TraceManager.addDev("Exception occurred when executing method " + _methodName + " Exception: " + e.getMessage()); + e.printStackTrace( System.out ); + return null; + } + } + public ImageIcon executeRetImageIconMethod(Class<?> c, String _methodName) { // We have a valid plugin. We now need to get the Method diff --git a/src/main/java/myutil/PluginManager.java b/src/main/java/myutil/PluginManager.java index 2a6b4e5cd3..e4308a1bbc 100644 --- a/src/main/java/myutil/PluginManager.java +++ b/src/main/java/myutil/PluginManager.java @@ -56,13 +56,12 @@ public class PluginManager { public static String PLUGIN_PATH = ""; public ArrayList<Plugin> plugins; - public ArrayList<Plugin> pluginPackages; public PluginManager() { plugins = new ArrayList<Plugin>(); - pluginPackages = new ArrayList<Plugin>(); } + public void preparePlugins(String path, String[] plugins, String[] packages) { PLUGIN_PATH = path; int cpt = 0; -- GitLab