Plugin

Feature Plugin Framework

1. Architecture Overview
2. Implementation Overview
3. Standard Procedures
  3.1 Writing A New Plugin
  3.2 Reimplementing Of An Existing Plugin
  3.3 Plugin Discovery
  3.4 Plugin Installation And Uninstallation

APPENDIX:
   A. Plugin example: Scripting language command
   B. Plugin example: GUI component

1. Architecture Overview

T-Plan Robot provides a generic feature plugin framework which allows to plugin custom code into the binaries without any need to recompile or reinstall the base product. It is designed to support the following scenarios:

  1. Replacement of existing functionality. As many objects in the T-Plan Robot Enterprise code base are designed as plugins, it is possible to install new code implementing the same functionality on top of the old one. The framework is in this case able to deactivate the old code and use the plugin one in its place. This mechanism allows to deliver safely bug fixes and custom feature enhancements to already existing customer installations.
  2. Delivery of new functionality. The point is to allow to implement new features on top of the exposed functional interfaces (i.e. Java interfaces defined as open to plugins). This allows to customize the product for particular customers and/or deliver on-demand features.

2. Implementation Overview

Plugin functionality is implemented in two packages, com.tplan.robot.plugin and com.tplan.robot.plugin.gui. The first one provides the core functionality with the plugin interface, default plugin map PluginMap.xml, plugin manager and base class for plugin factory implementations. The other package contains classes of the Plugin Manager dialog. Any user driven modifications of the plugins through the GUI save a local copy of the PluginMap.xml file to the user home folder. Should you experience any problems resulting from installed custom plugins , delete the file to revert to the factory settings.

3. Standard Procedures

The following chapters describe standard tasks when working with the plugin framework. The instructions describe just general steps. Fore more information on implementation details refer to the code documentation of the individual objects.

3.1 Writing A New Plugin

  1. Develop a class which implements both Plugin and one of the exposed functional interfaces listed in the PluginMap.xml map template or an abstract plugin class (if available). The class may not be private or abstract, must be publicly instantiable and must have a parameterless default constructor which creates a fully initialized plugin instance.
  2. Implement all methods of the Plugin interface according to the documentation. Make sure you understand the plugin mechanism, in particular role of the getCode() and getUniqueId() methods.
  3. Develop methods of the exposed interface to deliver the expected plugin functionality.
  4. Once the plugin is ready, compile your Java code to .class format or JAR/ZIP archive and follow the Plugin Installation And Uninstallation chapter on how to install it.

See the Appendix section of this document for examples of plugins .

3.2 Reimplementing Of An Existing Plugin

Reimplementing in this case means replacement of an already installed or built-in plugin. There are two standard situations:

  1. Plugin upgrade or eventual downgrade, i.e. reinstallation with a higher or lower plugin version,
  2. Replacement with a plugin from another vendor (producer).

The steps are:

  1. Develop a new plugin which returns the same code through the getCode() method as the one you intend to replace.
  2. To upgrade/downgrade implement the getVersion() method to return a higher/lower version number and let the getUniqueId() method return the same code as the original plugin. To implement the plugin as different vendor make the getUniqueId() method return a different code than the original plugin.

Refer to the Plugin Installation And Uninstallation chapter for information on the plugin installation.

3.3 Plugin Discovery

Plugins can be delivered to T-Plan Robot Enterprise installations either in form of compiled Java classes or a Java compatible archive (JAR or ZIP). The Plugin Manager provides a method able to scan a class path (folder with compiled Java classes) or a single JAR or ZIP file for plugins. It reviews all Java classes from the specified resource and finds all classes which implement the Plugin interface together with one of the exposed functional interfaces. For the list of exposed interfaces review the PluginMap.xml file. The method can be be employed programmatically by PluginManager.getAvailablePlugins(java.io.File). The Plugin Manager dialog also provides access to this functionality through the "Add JAR, ZIP Or Classpath..." button.

3.4 Plugin Installation And Uninstallation

Plugins can be installed in several ways:

  • RECOMMENDED ALTERNATIVE #1: Package your feature plugin as an installable plugin and make it compatible with the Update & Upgrade window. The Plugin Framework document describes the steps on a simple plugin example from this document.
  • RECOMMENDED ALTERNATIVE #2: Put the plugin JAR file into the <Robot_home>/plugins directory and restart Robot. It will auto install and enable all features discovered there on startup.
  • OBSOLETED/JAVA 8 ONLY: Use the Plugin Manager window available in the Robot GUI.
  • Advanced users may modify one of the XML maps (either the internal one PluginMap.xml or the external user-specific one specified by the PluginManager.EXTERNAL_PLUGIN_XML variable) and add an entry for the new plugin.
  • Plugins can be also installed and uninstalled from Java programs including Java test scripts. See the getAvailablePlugins(java.io.File), installPlugin(java.lang.String, java.lang.String, boolean, boolean) and uninstallPlugin(com.tplan.robot.plugin.Plugin) methods of PluginManager for more information.

APPENDIX

A. Plugin example: Scripting language command

This example demonstrates how to write a new T-Plan Robot Enterprise scripting language command called "Msg" which prints out the argument to the console window.
General Development Steps:

  1. Create a new project in your Java IDE (NetBeans, Eclipse, ...) and put the robot.jar file on the project library list.
  2. Create a new Java class which extends the com.tplan.robot.scripting.commands.AbstractCommandHandler class.
  3. Implement at least the getCommandNames(), validate() and execute() methods. Java source code of a simple example of a command called "msg" printing a message into the console is available below.
  4. Build the JAR file with the command class and plug it into T-Plan Robot Enterprise. 

Java Code:

com/tplan/robot/scripting/commands/impl/ConsoleMessageCommand.java
/*
* T-Plan Robot Enterprise, automated testing tool based on remote desktop technologies.
* Copyright (C) 2010 T-Plan Ltd (http://www.t-plan.com),
*/
package com.tplan.robot.scripting.commands.impl;

import com.tplan.robot.scripting.ScriptingContext;
import com.tplan.robot.scripting.SyntaxErrorException;
import com.tplan.robot.scripting.commands.AbstractCommandHandler;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
* Example of a simple custom command which prints out a message into
* the console using <code>System.out.println()</code>.
*/
public class ConsoleMessageCommand extends AbstractCommandHandler {

/**
* Get the command name ("msg").
* @return command name.
*/
public String[] getCommandNames() {
return new String[] {"msg"};
}

/**
* Compile command arguments and parameters. This command accepts just one
* mandatory argument which represents the text to be printed out into the console.
*
* @param params list of arguments and parameter names.
* @param values map of parameters and their values parsed from the [param]=[value] pairs
*
@param variableContainer optional container for processed parameters.
* Not used by this command.
* @param context scripting context.
* @throws com.tplan.robot.scripting.SyntaxErrorException on invalid command syntax.
*/
public void validate(List params, Map values, Map variableContainer, ScriptingContext context) throws SyntaxErrorException {
if (params.size() != 1) {
throw new SyntaxErrorException("The Msg command must have exactly one argument.");
}
}

/**
* Execute command.
*
* @param params list of arguments and parameter names.
* @param values map of parameters and their values parsed from the [param]=[value] pairs
* @param context scripting context.
* @throws com.tplan.robot.scripting.SyntaxErrorException on invalid command syntax.
*/
public int execute(List params, Map values, ScriptingContext context) throws SyntaxErrorException, IOException {
validate(params, values, values, context);
System.out.println(params.get(0));
return 0;
}

/**
* Overriden method to indicate that this command can execute even if the
* tool is not connected to any desktop.
* @return always returns true.
*/
@Override
public boolean canRunWithoutConnection() {
return true;
}
}

Installation:

  1. Start T-Plan Robot Enterprise GUI (offline mode is OK).
  2. Select Tools->Plugins to start the Plugin Manager window.
  3. Select the "Available Plugins" tab and click the "Add JAR, Zip Or Class Path" button. Navigate to the plugin JAR file.
  4. The window displays that there's one available plugin. Hit Install to install it and restart the tool.
  5. Type the command in the script editor:

Msg "hello world"

Then execute the script and check the console window for the printed text. A screen shot follows:



B. Plugin example: GUI component

This example demonstrates how to create a simple "Hello world" window and put it into the T-Plan Robot Enterprise menu and tool bar.
General Development Steps:

  1. Create a new project in your Java IDE (NetBeans, Eclipse, ...) and put the robot.jar file on the project library list.
  2. Create a new Java class which implements the com.tplan.robot.gui.GuiComponent and com.tplan.robot.plugin.Plugin interfaces.
  3. Implement methods of both interfaces. To add the window into the application menu and tool bar use methods getJMenuBar() and getToolBar() of the main window instance (../com/tplan/robot/gui/MainFrame.htmlcom.tplan.robot.gui.MainFrame) passed as argument to the setMainFrame() method of the GuiComponent interface.
  4. Build the JAR file with the plugin class and plug it into T-Plan Robot Enterprise. 

Java Code:

pluginexamples/GuiPluginExample.java

/*
* T-Plan Robot Enterprise, automated testing tool based on remote desktop technologies.
* Copyright (C) 2010 T-Plan Ltd (http://www.t-plan.com),
*/
package pluginexamples;

import com.tplan.robot.ApplicationSupport;
import com.tplan.robot.gui.ActionManager;
import com.tplan.robot.gui.GuiComponent;
import com.tplan.robot.gui.MainFrame;
import com.tplan.robot.plugin.DependencyMissingException;
import com.tplan.robot.plugin.Plugin;
import com.tplan.robot.plugin.PluginManager;
import com.tplan.robot.util.Utils;
import java.awt.Component;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;
import javax.swing.AbstractButton;
import javax.swing.JButton;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JToolBar;

/**
* <p>Example of a T-Plan Robot Enterprise plugin which adds a new item called "Hello"
* to the Tools menu and a new button labeled "Hello" to the tool bar. The action
* will open a dummy message window saying "Hello".</p>
*
* <p>To change the message window modify the content of the
* {@link #actionPerformed(java.awt.event.ActionEvent)}
* method of this class. Note that you don't have to reinstall the plugin after
* every code change as long as you keep the plugin code ({@link #getCode()}) and
* the unique ID ({@link #getUniqueId()}) untouched. You only have to restart
* the Robot's GUI to pick up the recompiled classes or JAR.</p>
*/
public class GuiPluginExample implements Plugin, GuiComponent, ActionListener {

JMenuItem mi;
JButton btn;

/**
* Method from the GuiComponent interface. It gets called when the GUI starts
* up and the main window (MainFrame) gets initialized.
* @param frame the Robot's GUI window.
*/
public void setMainFrame(MainFrame frame) {

// The name is "Tools" but we rather load the string from the resource bundle.
// This makes the plugin robust against menu name changes and/or eventual
// localization into another language. Labels of Robot's menu items are located
// in the Messages_en.properties file and they are always in form of "menu.<action>Text".
// See the "Data And Text File List"document in Robot's documentation.
// http://www.t-plan.com/robot/docs/v2.2ee/api/docs/files.html
String name = ApplicationSupport.getString("menu.ToolsText");

// Remove the evenual hot key which is typically after comma
if (name.contains(ActionManager.HOT_KEY_SEPARATOR)) {
name = name.substring(0, name.indexOf(ActionManager.HOT_KEY_SEPARATOR));
}

// Locate the Tools menu
JMenu m, toolsMenu = null;
JMenuBar mb = frame.getJMenuBar();

// Iterate over all menus of the main window and locate the "Tools" one
for (int i = 0; i < mb.getMenuCount(); i++) {
m = mb.getMenu(i);
if (m.getText().equals(name)) {
toolsMenu = m;
break;
}
}

// Fallback mechanism - if "Tools" is not found, use the first menu group
if (toolsMenu == null) {
toolsMenu = mb.getMenu(0);
}

// Create and add the "Hello" menu item.
mi = new JMenuItem("Hello");
mi.addActionListener(this);
toolsMenu.add(mi);

// Create the tool bar button.
btn = new JButton("Hello");
btn.setBorderPainted(false);
btn.setOpaque(false);
btn.setMargin(new Insets(1, 1, 1, 1));
btn.addActionListener(this);

// This piece of code shows how to insert the new tool bar button
// to a certain place in the tool bar. This example will put the tool
// bar button right after the "Preferences" one.
// The code uses the action command "preferences" to find the button.
// The action commands are defined together with the default tool bar
// structure in the MenuAndToolbar.properties file. See the "Data And Text File List"
// document in Robot's documentation.
// http://www.t-plan.com/robot/docs/v2.2ee/api/docs/files.html
JToolBar toolBar = frame.getToolBar();
final int cnt = toolBar.getComponentCount();
Component c;
for (int i = 0; i < cnt; i++) {
c = toolBar.getComponent(i);
if (c instanceof AbstractButton && "preferences".equals(((AbstractButton) c).getActionCommand())) {
toolBar.add(btn, i + 1);
return;
}
}

// Default location -> end of tool bar
toolBar.add(btn);
}

// ActionListener INTERFACE METHODS ========================================
/**
* Implementation of the {@link ActionListener} interface which gets called
* when either the menu item or the tool bar button are selected. The method
* just displays a dummy message box saying "Hello"
* @param e an action event.
*/
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(MainFrame.getInstance(), "Hello");
}

// Plugin INTERFACE METHODS ================================================
public String getCode() {
return "hello GUI plugin";
}

public String getDisplayName() {
return "GUI Plugin Example";
}

public String getDescription() {
return "Example of a GUI plugin which installs both into the menu " +
"and tool bar and displays a simple message of \"Hello\"";
}

public String getVendorName() {
return ApplicationSupport.APPLICATION_NAME;
}

public String getSupportContact() {
return ApplicationSupport.APPLICATION_SUPPORT_CONTACT;
}

public int[] getVersion() {
return Utils.getVersion();
}

public Class getImplementedInterface() {
return GuiComponent.class;
}

public boolean requiresRestart() {
return true;
}

public String getVendorHomePage() {
return ApplicationSupport.APPLICATION_HOME_PAGE;
}

public Date getDate() {
return Utils.getReleaseDate();
}

public String getUniqueId() {
return "TPlan_examples_GUI_plugin";
}

public int[] getLowestSupportedVersion() {
return Utils.getVersion();
}

public String getMessageBeforeInstall() {
return null;
}

public String getMessageAfterInstall() {
return null;
}

public void checkDependencies(PluginManager manager) throws DependencyMissingException {
}
}

Installation:

  1. Start T-Plan Robot Enterprise GUI (offline mode is OK).
  2. Select Tools->Plugins to start the Plugin Manager window.
  3. Select the "Available Plugins" tab and click the "Add JAR, Zip Or Class Path" button. Navigate to the plugin JAR file.
  4. The window displays that there's one available plugin. Hit Install to install it and restart the tool.
  5. Check the Tools menu and tool bar for the Hello item. When selected, a simple "Hello" message box appears. A screen shot follows.