You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@taverna.apache.org by st...@apache.org on 2015/02/17 12:48:50 UTC

[31/50] [abbrv] incubator-taverna-workbench-common-activities git commit: taverna-rest-activity-ui/

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/11c47f2b/src/main/resources/net/sf/taverna/t2/activities/rest/ui/config/mediatypes.txt
----------------------------------------------------------------------
diff --git a/src/main/resources/net/sf/taverna/t2/activities/rest/ui/config/mediatypes.txt b/src/main/resources/net/sf/taverna/t2/activities/rest/ui/config/mediatypes.txt
deleted file mode 100644
index 4f0f0f4..0000000
--- a/src/main/resources/net/sf/taverna/t2/activities/rest/ui/config/mediatypes.txt
+++ /dev/null
@@ -1,65 +0,0 @@
-application/atom+xml
-application/http
-application/javascript
-application/json
-application/octet-stream
-application/ogg
-application/pdf
-application/postscript
-application/rdf+xml
-application/sparql-query
-application/sparql-results+xml
-application/vnd.taverna.scufl+xml
-application/vnd.taverna.t2flow+xml
-application/x-gzip
-application/x-rar-compressed
-application/x-shockwave-flash
-application/x-tar
-application/x-www-form-urlencoded
-application/xhtml+xml
-application/xml
-application/zip
-audio/mp4
-audio/mpeg
-audio/mpeg4-generic
-audio/ogg
-audio/vnd.wave
-audio/vorbis
-audio/webm
-audio/x-ms-wma
-image/gif
-image/jpeg
-image/png
-image/svg+xml
-image/tiff
-image/vnd.microsoft.icon
-message/http
-message/rfc822
-multipart/alternative
-multipart/byteranges
-multipart/digest
-multipart/encrypted
-multipart/form-data
-multipart/mixed
-multipart/related
-multipart/signed
-text/css
-text/csv
-text/html
-text/javascript
-text/n3
-text/plain
-text/tab-separated-values
-text/turtle
-text/uri-list
-text/vcard
-text/xml
-video/H264
-video/MPV
-video/mp4
-video/mpeg
-video/mpeg4-generic
-video/ogg
-video/quicktime
-video/webm
-video/x-ms-wmv

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/11c47f2b/src/main/resources/net/sf/taverna/t2/activities/rest/ui/servicedescription/service_type_rest.png
----------------------------------------------------------------------
diff --git a/src/main/resources/net/sf/taverna/t2/activities/rest/ui/servicedescription/service_type_rest.png b/src/main/resources/net/sf/taverna/t2/activities/rest/ui/servicedescription/service_type_rest.png
deleted file mode 100644
index a4276c2..0000000
Binary files a/src/main/resources/net/sf/taverna/t2/activities/rest/ui/servicedescription/service_type_rest.png and /dev/null differ

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/11c47f2b/taverna-rest-activity-ui/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-rest-activity-ui/pom.xml b/taverna-rest-activity-ui/pom.xml
new file mode 100644
index 0000000..99ac649
--- /dev/null
+++ b/taverna-rest-activity-ui/pom.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>net.sf.taverna</groupId>
+		<artifactId>taverna-parent</artifactId>
+		<version>3.0.1-SNAPSHOT</version>
+	</parent>
+	<groupId>net.sf.taverna.t2.ui-activities</groupId>
+	<artifactId>rest-activity-ui</artifactId>
+        <version>2.0-SNAPSHOT</version>
+	<packaging>bundle</packaging>
+	<name>REST Activity - UI bindings</name>
+
+	<dependencies>
+		<dependency>
+			<groupId>net.sf.taverna.t2.activities</groupId>
+			<artifactId>rest-activity</artifactId>
+			<version>${t2.activities.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.taverna.t2.ui-api</groupId>
+			<artifactId>activity-palette-api</artifactId>
+			<version>${t2.ui.api.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.taverna.t2.ui-api</groupId>
+			<artifactId>menu-api</artifactId>
+			<version>${t2.ui.api.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.taverna.t2.ui-api</groupId>
+			<artifactId>contextual-views-api</artifactId>
+			<version>${t2.ui.api.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.taverna.t2.ui-api</groupId>
+			<artifactId>workbench-api</artifactId>
+			<version>${t2.ui.api.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.taverna.t2.ui-api</groupId>
+			<artifactId>report-api</artifactId>
+			<version>${t2.ui.api.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.taverna.t2.ui-components</groupId>
+			<artifactId>workflow-view</artifactId>
+			<version>${t2.ui.components.version}</version>
+		</dependency>
+	</dependencies>
+	<repositories>
+		<repository>
+			<releases />
+			<snapshots>
+				<enabled>false</enabled>
+			</snapshots>
+			<id>mygrid-repository</id>
+			<name>myGrid Repository</name>
+			<url>http://www.mygrid.org.uk/maven/repository
+			</url>
+		</repository>
+		<repository>
+			<releases>
+				<enabled>false</enabled>
+			</releases>
+			<snapshots />
+			<id>mygrid-snapshot-repository</id>
+			<name>myGrid Snapshot Repository</name>
+			<url>http://www.mygrid.org.uk/maven/snapshot-repository</url>
+		</repository>
+	</repositories>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/11c47f2b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/config/HTTPHeadersTableModel.java
----------------------------------------------------------------------
diff --git a/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/config/HTTPHeadersTableModel.java b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/config/HTTPHeadersTableModel.java
new file mode 100644
index 0000000..30507c9
--- /dev/null
+++ b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/config/HTTPHeadersTableModel.java
@@ -0,0 +1,119 @@
+package net.sf.taverna.t2.activities.rest.ui.config;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+
+import javax.swing.table.AbstractTableModel;
+
+@SuppressWarnings("serial")
+public class HTTPHeadersTableModel extends AbstractTableModel {
+
+    protected String[] columnNames;
+    protected ArrayList<ArrayList<String>> data;
+
+    public HTTPHeadersTableModel() {
+    	columnNames = new String[] {"HTTP Header Name", "HTTP Header Value"};
+    	data = new ArrayList<ArrayList<String>>();
+    }
+
+    public String getColumnName(int column) {
+        return columnNames[column];
+    }
+
+    public boolean isCellEditable(int row, int column) {
+        return true;
+    }
+
+    public int getColumnCount()
+    {
+        return columnNames.length;
+    }
+
+    public int getRowCount()
+    {
+        return data.size();
+    }
+
+    public Object getValueAt(int row, int column)
+    {
+        return data.get(row).get(column);
+    }
+
+    public void setValueAt(Object value, int row, int column) {
+        if ((row < 0) || (column < 0)) {
+          throw new IllegalArgumentException("Invalid row/column setting");
+        }
+        data.get(row).set(column, (String)value);
+      }
+    
+    /**
+     * Get the class at of the cells at the given column position.
+     */
+    public Class<? extends Object> getColumnClass(int iCol)
+    {
+        return getValueAt(0, iCol).getClass();
+    }
+
+    
+	public void addEmptyRow() {
+        data.add(new ArrayList<String>(Arrays.asList("", ""))); // add empty row
+        fireTableRowsInserted(
+           data.size() - 1,
+           data.size() - 1);
+    }
+	
+	public void addRow(ArrayList<String> headerValuePair) {
+        data.add(headerValuePair);
+        fireTableRowsInserted(
+           data.size() - 1,
+           data.size() - 1);
+    }
+	
+	public void removeRow(int row)
+	{
+		if (row >=0 && row < data.size()){
+			data.remove(row);
+			fireTableRowsDeleted(row, row);
+		}
+	}
+
+	public ArrayList<ArrayList<String>> getHTTPHeaderData(){
+		// Return a deep copy of the 2-dimensional array
+		return deepCopy(data);
+	}
+	
+	public void setHTTPHeaderData(ArrayList<ArrayList<String>> data){
+		this.data = deepCopy(data);
+		fireTableChanged(null);
+	}
+	
+	public ArrayList<String> getHTTPHeaderNames(){
+		ArrayList<String> headerNames = new ArrayList<String>();
+		for (ArrayList<String> headerNameValuePair : data){
+			headerNames.add(headerNameValuePair.get(0));
+		}
+		return headerNames;
+	}
+	
+	public ArrayList<String> getHTTPHeaderValues(){
+		ArrayList<String> headerValues = new ArrayList<String>();
+		for (ArrayList<String> headerNameValuePair : data){
+			headerValues.add(headerNameValuePair.get(1));
+		}
+		return headerValues;
+	}
+	
+	public static ArrayList<ArrayList<String>> deepCopy(ArrayList<ArrayList<String>> src)
+	{
+	    ArrayList<ArrayList<String>> dest = new ArrayList<ArrayList<String>>();
+
+	    for (int i = 0; i< src.size(); i++){ 	
+	    	dest.add(new ArrayList<String>(Arrays.asList(new String[src.get(i).size()])));  
+	    	Collections.copy(dest.get(i), src.get(i));
+	    }
+	    return dest;
+	}
+
+}
+

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/11c47f2b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/config/RESTActivityConfigurationPanel.java
----------------------------------------------------------------------
diff --git a/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/config/RESTActivityConfigurationPanel.java b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/config/RESTActivityConfigurationPanel.java
new file mode 100644
index 0000000..d6b46e1
--- /dev/null
+++ b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/config/RESTActivityConfigurationPanel.java
@@ -0,0 +1,670 @@
+package net.sf.taverna.t2.activities.rest.ui.config;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Scanner;
+
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.JTextField;
+import javax.swing.ListSelectionModel;
+
+import net.sf.taverna.t2.activities.rest.RESTActivity;
+import net.sf.taverna.t2.activities.rest.RESTActivity.DATA_FORMAT;
+import net.sf.taverna.t2.activities.rest.RESTActivity.HTTP_METHOD;
+import net.sf.taverna.t2.activities.rest.RESTActivityConfigurationBean;
+import net.sf.taverna.t2.activities.rest.URISignatureHandler;
+import net.sf.taverna.t2.activities.rest.URISignatureHandler.URISignatureParsingException;
+import net.sf.taverna.t2.workbench.MainWindow;
+import net.sf.taverna.t2.workbench.ui.views.contextualviews.activity.MultiPageActivityConfigurationPanel;
+import uk.org.taverna.commons.services.ServiceRegistry;
+import uk.org.taverna.scufl2.api.activity.Activity;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+@SuppressWarnings("serial")
+public class RESTActivityConfigurationPanel extends MultiPageActivityConfigurationPanel {
+	private static final Icon infoIcon = new ImageIcon(
+			RESTActivityConfigurationPanel.class.getResource("information.png"));
+
+	// GENERAL tab
+	private JComboBox<HTTP_METHOD> cbHTTPMethod; // HTTP method of this REST activity
+	private JTextField tfURLSignature; // URL signature that determines its
+										// input ports
+	private JComboBox<String> cbAccepts; // for Accepts header
+	private JLabel jlContentTypeExplanation;
+	private JLabel jlContentTypeExplanationPlaceholder;
+	private JLabel jlContentType;
+	private JLabel jlContentTypeLabelPlaceholder; // this placeholder label will
+													// take up space of the
+													// ContentType combo-box
+													// when the latter is not
+													// shown
+	private JLabel jlContentTypeFieldPlaceholder;
+	private JComboBox<String> cbContentType; // for MIME type of data sent to the server
+										// by POST / PUT methods
+	private JLabel jlSendDataAs;
+	private JComboBox<DATA_FORMAT> cbSendDataAs;
+	private JLabel jlSendDataAsLabelPlaceholder;
+	private JLabel jlSendDataAsFieldPlaceholder;
+
+	// ADVANCED tab
+	private JCheckBox cbSendHTTPExpectHeader;
+	private JCheckBox cbShowRedirectionOutputPort;
+	private JCheckBox cbShowActualUrlPort;
+	private JCheckBox cbShowResponseHeadersPort;
+	private JCheckBox cbEscapeParameters;
+	private JButton addHeaderButton;
+	private JButton removeHeaderButton;
+	private JTable httpHeadersTable;
+	private HTTPHeadersTableModel httpHeadersTableModel;
+
+	private String[] mediaTypes;
+
+	private final ServiceRegistry serviceRegistry;
+
+	public RESTActivityConfigurationPanel(Activity activity, ServiceRegistry serviceRegistry) {
+		super(activity);
+		this.serviceRegistry = serviceRegistry;
+		initialise();
+	}
+
+	@Override
+	protected void initialise() {
+		super.initialise();
+		removeAllPages();
+		addPage("General", createGeneralTab());
+		addPage("Advanced", createAdvancedTab());
+		refreshConfiguration();
+	}
+
+	@Override
+	public void noteConfiguration() {
+		ObjectNode requestNode = json.objectNode();
+
+		String methodName = ((HTTP_METHOD) cbHTTPMethod.getSelectedItem()).name();
+		requestNode.put("httpMethod", methodName);
+		requestNode.put("absoluteURITemplate", tfURLSignature.getText().trim());
+
+		ArrayNode headersNode = requestNode.arrayNode();
+		headersNode.addObject().put("header", "Accept").put("value", (String) cbAccepts.getSelectedItem());
+		headersNode.addObject().put("header", "Content-Type").put("value", (String) cbContentType.getSelectedItem());
+		if (cbSendHTTPExpectHeader.isSelected()) {
+			headersNode.addObject().put("header", "Expect").put("value", "100-continue");
+		}
+		ArrayList<String> headerNames = httpHeadersTableModel.getHTTPHeaderNames();
+		ArrayList<String> headerValues = httpHeadersTableModel.getHTTPHeaderValues();
+		for (int i = 0; i < headerNames.size(); i++) {
+			headersNode.addObject().put("header", headerNames.get(i)).put("value", headerValues.get(i));
+		}
+
+		requestNode.set("headers", headersNode);
+		json.set("request", requestNode);
+
+		json.put("outgoingDataFormat", ((DATA_FORMAT) cbSendDataAs.getSelectedItem()).name());
+		json.put("showRedirectionOutputPort", cbShowRedirectionOutputPort
+				.isSelected());
+		json.put("showActualURLPort", cbShowActualUrlPort.isSelected());
+		json.put("showResponseHeadersPort", cbShowResponseHeadersPort.isSelected());
+		json.put("escapeParameters", cbEscapeParameters.isSelected());
+
+		configureInputPorts(serviceRegistry);
+		configureOutputPorts(serviceRegistry);
+	}
+
+	/**
+	 * Check that user values in the UI are valid.
+	 */
+	@Override
+	public boolean checkValues() {
+		// HTTP method is a fixed selection combo-box - no validation required
+
+		// URL signature must be present and be valid
+		String candidateURLSignature = tfURLSignature.getText().trim();
+		if (candidateURLSignature == null
+				|| candidateURLSignature.length() == 0) {
+			JOptionPane.showMessageDialog(MainWindow.getMainWindow(),
+					"URL signature must not be empty",
+					"REST Activity Configuration - Warning",
+					JOptionPane.WARNING_MESSAGE);
+			return (false);
+		} else {
+			try {
+				// Test if any exceptions will be thrown - if not, proceed to
+				// other validations
+				URISignatureHandler.validate(candidateURLSignature);
+			} catch (URISignatureParsingException e) {
+				JOptionPane.showMessageDialog(MainWindow.getMainWindow(), e
+						.getMessage(), "REST Activity Configuration - Warning",
+						JOptionPane.WARNING_MESSAGE);
+				return (false);
+			}
+
+			// Test if the URL string contains "unsafe" characters, i.e. characters
+			// that need URL-encoding.
+			// From RFC 1738: "...Only alphanumerics [0-9a-zA-Z], the special
+			// characters "$-_.+!*'()," (not including the quotes) and reserved
+			// characters used for their reserved purposes may be
+			// used unencoded within a URL."
+			// Reserved characters are: ";/?:@&=" ..." (excluding quotes) and "%" used
+			// for escaping.
+			// We do not warn the user if they have not properly enclosed parameter
+			// names in curly braces as this check is already being done elsewhere in the code.
+			// We do not check the characters in parameter names either.
+			try {
+				// Test if any exceptions will be thrown - if not, proceed to
+				// other validations
+				URISignatureHandler.checkForUnsafeCharacters(candidateURLSignature);
+			} catch (URISignatureParsingException e) {
+				JOptionPane.showMessageDialog(MainWindow.getMainWindow(), e
+						.getMessage(), "REST Activity Configuration - Warning",
+						JOptionPane.WARNING_MESSAGE);
+				return (false);
+			}
+
+			// Other HTTP headers configured must not have empty names
+			ArrayList<String> otherHTTPHeaderNames = httpHeadersTableModel.getHTTPHeaderNames();
+			for (String headerName : otherHTTPHeaderNames){
+				if (headerName.equals("")){
+					JOptionPane.showMessageDialog(MainWindow.getMainWindow(), "One of the HTTP header names is empty", "REST Activity Configuration - Warning",
+							JOptionPane.WARNING_MESSAGE);
+					return false;
+				}
+			}
+		}
+
+		// All valid, return true
+		return true;
+	}
+
+	/**
+	 * Update GUI from a changed configuration bean (perhaps by undo / redo).
+	 */
+	@Override
+	public void refreshConfiguration() {
+		RESTActivityConfigurationBean configBean = new RESTActivityConfigurationBean(json);
+
+		cbHTTPMethod.setSelectedItem(configBean.getHttpMethod());
+		tfURLSignature.setText(configBean.getUrlSignature());
+		tfURLSignature.setCaretPosition(0);
+		cbAccepts.setSelectedItem(configBean.getAcceptsHeaderValue());
+		cbContentType.setSelectedItem(configBean.getContentTypeForUpdates());
+		cbSendDataAs.setSelectedItem(configBean.getOutgoingDataFormat());
+		cbSendHTTPExpectHeader.setSelected(configBean
+				.getSendHTTPExpectRequestHeader());
+		cbShowRedirectionOutputPort.setSelected(configBean
+				.getShowRedirectionOutputPort());
+		cbShowActualUrlPort.setSelected(configBean.getShowActualUrlPort());
+		cbShowResponseHeadersPort.setSelected(configBean.getShowResponseHeadersPort());
+		cbEscapeParameters.setSelected(configBean.getEscapeParameters());
+		httpHeadersTableModel.setHTTPHeaderData(configBean.getOtherHTTPHeaders());
+	}
+
+	private JPanel createGeneralTab() {
+		JPanel jpGeneral = new JPanel(new GridBagLayout());
+		GridBagConstraints c = new GridBagConstraints();
+		// All components to be anchored WEST
+		c.anchor = GridBagConstraints.WEST;
+
+		c.gridx = 0;
+		c.gridy = 0;
+		c.gridwidth = 1;
+		c.insets = new Insets(7, 7, 3, 3);
+		c.weightx = 0.0;
+		c.fill = GridBagConstraints.NONE;
+		JLabel labelMethod = new JLabel("HTTP Method:", infoIcon, JLabel.LEFT);
+		labelMethod
+				.setToolTipText("<html>HTTP method determines how a request to the remote server will be made.<br><br>"
+						+ "Supported HTTP methods are normally used for different purposes:<br>"
+						+ "<b>GET</b> - to fetch data;<br>"
+						+ "<b>POST</b> - to create new resources;<br>"
+						+ "<b>PUT</b> - to update existing resources;<br>"
+						+ "<b>DELETE</b> - to remove existing resources.<br><br>"
+						+ "Documentation of the server that is about to be used may suggest the<br>"
+						+ "HTTP method that should be used.</html>");
+		jpGeneral.add(labelMethod, c);
+
+		// the HTTP method combo-box will always contain the same values - it is
+		// the selected
+		// method which is important; therefore, can prepopulate as the set of
+		// values is known
+		c.gridx++;
+		c.insets = new Insets(7, 3, 3, 7);
+		c.fill = GridBagConstraints.HORIZONTAL;
+		c.weightx = 1.0;
+		cbHTTPMethod = new JComboBox<>(HTTP_METHOD.values());
+		cbHTTPMethod.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				boolean contentTypeSelEnabled = RESTActivity
+						.hasMessageBodyInputPort((HTTP_METHOD) cbHTTPMethod
+								.getSelectedItem());
+
+				jlContentTypeExplanation.setVisible(contentTypeSelEnabled);
+				jlContentType.setVisible(contentTypeSelEnabled);
+				cbContentType.setVisible(contentTypeSelEnabled);
+				jlSendDataAs.setVisible(contentTypeSelEnabled);
+				cbSendDataAs.setVisible(contentTypeSelEnabled);
+
+				jlContentTypeExplanationPlaceholder
+						.setVisible(!contentTypeSelEnabled);
+				jlContentTypeLabelPlaceholder
+						.setVisible(!contentTypeSelEnabled);
+				jlContentTypeFieldPlaceholder
+						.setVisible(!contentTypeSelEnabled);
+				jlSendDataAsLabelPlaceholder.setVisible(!contentTypeSelEnabled);
+				jlSendDataAsFieldPlaceholder.setVisible(!contentTypeSelEnabled);
+			}
+		});
+		jpGeneral.add(cbHTTPMethod, c);
+
+		c.gridx = 0;
+		c.gridy++;
+		c.insets = new Insets(3, 7, 3, 3);
+		c.fill = GridBagConstraints.NONE;
+		c.weightx = 0.0;
+		JLabel labelString = new JLabel("URL Template:", infoIcon, JLabel.LEFT);
+		labelString
+				.setToolTipText("<html>URL template enables to define a URL with <b>configurable<br>"
+						+ "parameters</b> that will be used to access a remote server.<br><br>"
+						+ "The template may contain zero or more <b>parameters</b> - each<br>"
+						+ "enclosed within curly braces <b>\"{\"</b> and <b>\"}\"</b>.<br>"
+						+ "Taverna will automatically create an individual input port for<br>"
+						+ "this activity for each parameter.<br><br>"
+						+ "Values extracted from these input ports during the workflow<br>"
+						+ "execution these will be used to replace the parameters to<br>"
+						+ "produce complete URLs.<br><br>"
+						+ "For example, if the URL template is configured as<br>"
+						+ "\"<i>http://www.myexperiment.org/user.xml?id={userID}</i>\", a<br>"
+						+ "single input port with the name \"<i>userID</i>\" will be created.</html>");
+		labelString.setLabelFor(tfURLSignature);
+		jpGeneral.add(labelString, c);
+
+		c.gridx++;
+		c.insets = new Insets(3, 3, 3, 7);
+		c.fill = GridBagConstraints.HORIZONTAL;
+		c.weightx = 1.0;
+		tfURLSignature = new JTextField(40);
+		tfURLSignature.addFocusListener(new FocusListener() {
+			public void focusGained(FocusEvent e) {
+				tfURLSignature.selectAll();
+			}
+
+			public void focusLost(FocusEvent e) { /* do nothing */
+			}
+		});
+		jpGeneral.add(tfURLSignature, c);
+
+		c.gridx = 0;
+		c.gridwidth = 2;
+		c.gridy++;
+		c.weightx = 0.0;
+		c.fill = GridBagConstraints.NONE;
+		c.insets = new Insets(18, 7, 3, 7);
+		JLabel jlAcceptsExplanation = new JLabel(
+				"Preferred MIME type for data to be fetched from the remote server --");
+		jpGeneral.add(jlAcceptsExplanation, c);
+		c.gridwidth = 1;
+
+		c.gridx = 0;
+		c.gridy++;
+		c.insets = new Insets(3, 7, 3, 3);
+		c.weightx = 0.0;
+		c.fill = GridBagConstraints.NONE;
+		JLabel jlAccepts = new JLabel("'Accept' header:", infoIcon, JLabel.LEFT);
+		jlAccepts
+				.setToolTipText("<html>Select a MIME type from the drop-down menu or type your own.<br>Select blank if you do not want this header to be set.</br>");
+		jlAccepts.setLabelFor(cbAccepts);
+		jpGeneral.add(jlAccepts, c);
+
+		c.gridx++;
+		c.insets = new Insets(3, 3, 3, 7);
+		c.weightx = 1.0;
+		c.fill = GridBagConstraints.HORIZONTAL;
+		cbAccepts = new JComboBox<>(getMediaTypes());
+		cbAccepts.setEditable(true);
+		cbAccepts.getEditor().getEditorComponent().addFocusListener(
+				new FocusListener() {
+					public void focusGained(FocusEvent e) {
+						cbAccepts.getEditor().selectAll();
+					}
+
+					public void focusLost(FocusEvent e) { /* do nothing */
+					}
+				});
+		jpGeneral.add(cbAccepts, c);
+
+		c.gridx = 0;
+		c.gridwidth = 2;
+		c.gridy++;
+		c.insets = new Insets(18, 7, 3, 7);
+		c.weightx = 0.0;
+		c.fill = GridBagConstraints.NONE;
+		jlContentTypeExplanation = new JLabel(
+				"MIME type of data that will be sent to the remote server --");
+		jpGeneral.add(jlContentTypeExplanation, c);
+		c.gridwidth = 1;
+
+		c.gridx = 0;
+		c.gridy++;
+		c.insets = new Insets(3, 7, 3, 3);
+		c.weightx = 0.0;
+		c.fill = GridBagConstraints.NONE;
+		jlContentType = new JLabel("'Content-Type' header:", infoIcon,
+				JLabel.LEFT);
+		jlContentType
+				.setToolTipText("<html>Select a MIME type from the drop-down menu or type your own.<br>Select blank if you do not want this header to be set.</html>");
+		jlContentType.setLabelFor(cbContentType);
+		jpGeneral.add(jlContentType, c);
+
+		c.gridx++;
+		c.insets = new Insets(3, 3, 3, 7);
+		c.weightx = 1.0;
+		c.fill = GridBagConstraints.HORIZONTAL;
+		cbContentType = new JComboBox<>(getMediaTypes());
+		cbContentType.setEditable(true);
+		cbContentType.getEditor().getEditorComponent().addFocusListener(
+				new FocusListener() {
+					public void focusGained(FocusEvent e) {
+						cbContentType.getEditor().selectAll();
+					}
+
+					public void focusLost(FocusEvent e) { /* do nothing */
+					}
+				});
+		cbContentType.addActionListener(new ActionListener() {
+			public void actionPerformed(ActionEvent e) {
+				// change selection in the "Send data as" combo-box, based on
+				// the selection of Content-Type
+				String selectedContentType = (String) cbContentType
+						.getSelectedItem();
+				if (selectedContentType.startsWith("text")) {
+					cbSendDataAs.setSelectedItem(DATA_FORMAT.String);
+				} else {
+					cbSendDataAs.setSelectedItem(DATA_FORMAT.Binary);
+				}
+			}
+		});
+		jpGeneral.add(cbContentType, c);
+
+		c.gridx = 0;
+		c.gridwidth = 2;
+		c.gridy++;
+		c.insets = new Insets(18, 7, 3, 7);
+		c.weightx = 0.0;
+		c.fill = GridBagConstraints.NONE;
+		jlContentTypeExplanationPlaceholder = new JLabel();
+		jlContentTypeExplanationPlaceholder
+				.setPreferredSize(jlContentTypeExplanation.getPreferredSize());
+		jpGeneral.add(jlContentTypeExplanationPlaceholder, c);
+		c.gridwidth = 1;
+
+		c.gridx = 0;
+		c.gridy++;
+		c.insets = new Insets(3, 7, 3, 3);
+		c.weightx = 0.0;
+		c.fill = GridBagConstraints.NONE;
+		jlContentTypeLabelPlaceholder = new JLabel();
+		jlContentTypeLabelPlaceholder.setPreferredSize(jlContentType
+				.getPreferredSize());
+		jpGeneral.add(jlContentTypeLabelPlaceholder, c);
+
+		c.gridx++;
+		c.insets = new Insets(3, 3, 3, 7);
+		c.weightx = 1.0;
+		c.fill = GridBagConstraints.HORIZONTAL;
+		jlContentTypeFieldPlaceholder = new JLabel();
+		jlContentTypeFieldPlaceholder.setPreferredSize(cbContentType
+				.getPreferredSize());
+		jpGeneral.add(jlContentTypeFieldPlaceholder, c);
+
+		c.gridx = 0;
+		c.gridy++;
+		c.weightx = 0.0;
+		c.fill = GridBagConstraints.NONE;
+		c.insets = new Insets(3, 7, 8, 3);
+		jlSendDataAs = new JLabel("Send data as:", infoIcon, JLabel.LEFT);
+		jlSendDataAs
+				.setToolTipText("Select the format for the data to be sent to the remote server");
+		jlSendDataAs.setLabelFor(cbSendDataAs);
+		jpGeneral.add(jlSendDataAs, c);
+
+		c.gridx++;
+		c.insets = new Insets(3, 3, 8, 7);
+		c.weightx = 1.0;
+		c.fill = GridBagConstraints.HORIZONTAL;
+		cbSendDataAs = new JComboBox<>(DATA_FORMAT.values());
+		cbSendDataAs.setEditable(false);
+		jpGeneral.add(cbSendDataAs, c);
+
+		c.gridx = 0;
+		c.gridy++;
+		c.insets = new Insets(3, 7, 8, 3);
+		c.weightx = 0.0;
+		c.fill = GridBagConstraints.NONE;
+		jlSendDataAsLabelPlaceholder = new JLabel();
+		jlSendDataAsLabelPlaceholder.setPreferredSize(jlSendDataAs
+				.getPreferredSize());
+		jpGeneral.add(jlSendDataAsLabelPlaceholder, c);
+
+		c.gridx++;
+		c.insets = new Insets(3, 3, 8, 7);
+		c.weightx = 1.0;
+		c.fill = GridBagConstraints.HORIZONTAL;
+		jlSendDataAsFieldPlaceholder = new JLabel();
+		jlSendDataAsFieldPlaceholder.setPreferredSize(cbSendDataAs
+				.getPreferredSize());
+		jpGeneral.add(jlSendDataAsFieldPlaceholder, c);
+
+		JPanel finalPanel = new JPanel(new BorderLayout());
+		finalPanel.add(jpGeneral, BorderLayout.NORTH);
+		return (finalPanel);
+	}
+
+	private String[] getMediaTypes() {
+		if (mediaTypes != null) {
+			return mediaTypes;
+		}
+		List<String> types = new ArrayList<String>();
+		InputStream typesStream = getClass().getResourceAsStream(
+				"mediatypes.txt");
+		try {
+			// media types must be ASCII and can't have whitespace
+			Scanner scanner = new Scanner(typesStream, "ascii");
+			while (scanner.hasNext()) {
+				types.add(scanner.next());
+			}
+			scanner.close();
+		} finally {
+			try {
+				typesStream.close();
+			} catch (IOException ex) {
+			}
+		}
+		mediaTypes = types.toArray(new String[0]);
+
+		return mediaTypes;
+	}
+
+	private JPanel createAdvancedTab() {
+		JPanel jpAdvanced = new JPanel(new GridBagLayout());
+		GridBagConstraints c = new GridBagConstraints();
+
+		c.gridx = 0;
+		c.gridy = 0;
+		c.anchor = GridBagConstraints.WEST;
+		c.fill = GridBagConstraints.BOTH;
+		c.insets = new Insets(8, 10, 2, 4);
+		JLabel jlExpectHeaderInfoIcon = new JLabel(infoIcon);
+		jlExpectHeaderInfoIcon
+				.setToolTipText("<html>Ticking this checkbox may significantly improve performance when<br>"
+						+ "large volumes of data are sent to the remote server and a redirect<br>"
+						+ "from the original URL to the one specified by the server is likely.<br>"
+						+ "<br>"
+						+ "However, this checkbox <b>must not</b> be ticked to allow this activity<br>"
+						+ "to post updates to Twitter.</html>");
+		jpAdvanced.add(jlExpectHeaderInfoIcon, c);
+
+		c.gridx++;
+		c.weightx = 1.0;
+		c.insets = new Insets(8, 0, 2, 8);
+		cbSendHTTPExpectHeader = new JCheckBox(
+				"Send HTTP Expect request-header field");
+		jpAdvanced.add(cbSendHTTPExpectHeader, c);
+
+		c.gridx = 0;
+		c.gridy++;
+		c.weightx = 0;
+		c.insets = new Insets(2, 10, 5, 4);
+		JLabel jlShowRedirectionOutputPortInfoIcon = new JLabel(infoIcon);
+		jlShowRedirectionOutputPortInfoIcon
+				.setToolTipText("<html>\"Redirection\" output port displays the URL of the final redirect<br>"
+						+ "that has yielded the output data on the \"Response Body\" port.</html>");
+		jpAdvanced.add(jlShowRedirectionOutputPortInfoIcon, c);
+
+		c.gridx++;
+		c.weightx = 1.0;
+		c.insets = new Insets(2, 0, 5, 8);
+		cbShowRedirectionOutputPort = new JCheckBox(
+				"Show \"Redirection\" output port");
+		jpAdvanced.add(cbShowRedirectionOutputPort, c);
+
+		c.gridx = 0;
+		c.gridy++;
+		c.weightx = 0;
+		c.insets = new Insets(2, 10, 5, 4);
+		JLabel jlShowActualUrlPortInfoIcon = new JLabel(infoIcon);
+		jlShowActualUrlPortInfoIcon
+				.setToolTipText("<html>\"Actual URL\" output port displays the URL used by the REST service<br>"
+						+ "with the actual parameter values.</html>");
+		jpAdvanced.add(jlShowActualUrlPortInfoIcon, c);
+
+		c.gridx++;
+		c.weightx = 1.0;
+		c.insets = new Insets(2, 0, 5, 8);
+		cbShowActualUrlPort = new JCheckBox(
+				"Show \"Actual URL\" output port");
+		jpAdvanced.add(cbShowActualUrlPort, c);
+
+		c.gridx = 0;
+		c.gridy++;
+		c.weightx = 0;
+		c.insets = new Insets(2, 10, 5, 4);
+		JLabel jlShowResponseHeadersPortInfoIcon = new JLabel(infoIcon);
+		jlShowResponseHeadersPortInfoIcon
+				.setToolTipText("<html>\"Response headers\" output port displays the HTTP headers<br>"
+						+ "received from the final (after redirection) HTTP call.</html>");
+		jpAdvanced.add(jlShowResponseHeadersPortInfoIcon, c);
+
+		c.gridx++;
+		c.weightx = 1.0;
+		c.insets = new Insets(2, 0, 5, 8);
+		cbShowResponseHeadersPort = new JCheckBox(
+				"Show \"Response headers\" output port");
+		jpAdvanced.add(cbShowResponseHeadersPort, c);
+
+		c.gridx = 0;
+		c.gridy++;
+		c.weightx = 0;
+		c.insets = new Insets(2, 10, 5, 4);
+		JLabel jlEscapeParametersInfoIcon = new JLabel(infoIcon);
+		jlEscapeParametersInfoIcon
+				.setToolTipText("<html>Determines if parameters you pass to form the full URL<br>" +
+						" of the REST service will be URL-escaped.</html>");
+		jpAdvanced.add(jlEscapeParametersInfoIcon, c);
+
+		c.gridx++;
+		c.weightx = 1.0;
+		c.insets = new Insets(2, 0, 5, 8);
+		cbEscapeParameters = new JCheckBox("Escape URL parameter values");
+		jpAdvanced.add(cbEscapeParameters, c);
+
+		c.gridx = 0;
+		c.gridy++;
+		c.weightx = 0;
+		c.anchor = GridBagConstraints.WEST;
+		c.fill = GridBagConstraints.NONE;
+		c.insets = new Insets(2, 10, 5, 4);
+		JLabel jlHTTPHeadersInfoIcon = new JLabel(infoIcon);
+		jlHTTPHeadersInfoIcon
+				.setToolTipText("<html>Set additional HTTP headers</html>");
+		jpAdvanced.add(jlHTTPHeadersInfoIcon, c);
+
+		c.gridx = 1;
+		c.weightx = 0;
+		c.weighty = 0;
+		c.anchor = GridBagConstraints.WEST;
+		c.fill = GridBagConstraints.NONE;
+		c.insets = new Insets(2, 10, 5, 4);
+		addHeaderButton = new JButton("Add HTTP header");
+		addHeaderButton.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				httpHeadersTableModel.addEmptyRow();
+				httpHeadersTable.getSelectionModel().setSelectionInterval(httpHeadersTableModel.getRowCount() - 1, httpHeadersTableModel.getRowCount() - 1);			}
+		});
+		removeHeaderButton = new JButton("Remove HTTP header");
+		removeHeaderButton.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				int row = httpHeadersTable.getSelectedRow();
+				httpHeadersTableModel.removeRow(row);
+			}
+		});
+		JPanel buttonPanel = new JPanel();
+		buttonPanel.add(addHeaderButton, FlowLayout.LEFT);
+		buttonPanel.add(removeHeaderButton);
+		jpAdvanced.add(buttonPanel, c);
+
+		c.gridx = 1;
+		c.gridy++;
+		c.weightx = 0;
+		c.weighty = 1.0;
+		c.fill = GridBagConstraints.BOTH;
+		c.insets = new Insets(2, 10, 5, 4);
+		httpHeadersTableModel = new HTTPHeadersTableModel();
+		httpHeadersTable = new JTable(httpHeadersTableModel);
+		httpHeadersTable.setGridColor(Color.GRAY);
+		httpHeadersTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+		setVisibleRowCount(httpHeadersTable, 3);
+		JScrollPane headersTableScrollPane = new JScrollPane(httpHeadersTable);
+		jpAdvanced.add(headersTableScrollPane, c);
+
+		return (jpAdvanced);
+	}
+
+	/*
+	 * Based on http://www.javalobby.org/java/forums/t19559.html
+	 */
+	public static void setVisibleRowCount(JTable table, int visibleRows){
+	    int height = 0;
+	    for(int row = 0; row < visibleRows; row++)
+	        height += table.getRowHeight(row);
+
+	    table.setPreferredScrollableViewportSize(new Dimension(
+	            table.getPreferredScrollableViewportSize().width,
+	            height));
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/11c47f2b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/config/RESTActivityConfigureAction.java
----------------------------------------------------------------------
diff --git a/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/config/RESTActivityConfigureAction.java b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/config/RESTActivityConfigureAction.java
new file mode 100644
index 0000000..bfb50d0
--- /dev/null
+++ b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/config/RESTActivityConfigureAction.java
@@ -0,0 +1,51 @@
+package net.sf.taverna.t2.activities.rest.ui.config;
+
+import java.awt.Frame;
+import java.awt.event.ActionEvent;
+
+import net.sf.taverna.t2.servicedescriptions.ServiceDescriptionRegistry;
+import net.sf.taverna.t2.workbench.activityicons.ActivityIconManager;
+import net.sf.taverna.t2.workbench.edits.EditManager;
+import net.sf.taverna.t2.workbench.file.FileManager;
+import net.sf.taverna.t2.workbench.ui.actions.activity.ActivityConfigurationAction;
+import net.sf.taverna.t2.workbench.ui.views.contextualviews.activity.ActivityConfigurationDialog;
+import uk.org.taverna.commons.services.ServiceRegistry;
+import uk.org.taverna.scufl2.api.activity.Activity;
+
+@SuppressWarnings("serial")
+/**
+ * @author Sergejs Aleksejevs
+ * @author David Withers
+ */
+public class RESTActivityConfigureAction extends ActivityConfigurationAction {
+
+	private final EditManager editManager;
+	private final FileManager fileManager;
+	private final ServiceRegistry serviceRegistry;
+
+	public RESTActivityConfigureAction(Activity activity, Frame owner, EditManager editManager,
+			FileManager fileManager, ActivityIconManager activityIconManager,
+			ServiceDescriptionRegistry serviceDescriptionRegistry, ServiceRegistry serviceRegistry) {
+		super(activity, activityIconManager, serviceDescriptionRegistry);
+		this.editManager = editManager;
+		this.fileManager = fileManager;
+		this.serviceRegistry = serviceRegistry;
+	}
+
+	public void actionPerformed(ActionEvent e) {
+		ActivityConfigurationDialog currentDialog = ActivityConfigurationAction
+				.getDialog(getActivity());
+
+		if (currentDialog != null) {
+			currentDialog.toFront();
+			return;
+		}
+
+		RESTActivityConfigurationPanel panel = new RESTActivityConfigurationPanel(getActivity(), serviceRegistry);
+		ActivityConfigurationDialog dialog = new ActivityConfigurationDialog(getActivity(), panel,
+				editManager);
+
+		ActivityConfigurationAction.setDialog(getActivity(), dialog, fileManager);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/11c47f2b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/menu/AddRESTTemplateAction.java
----------------------------------------------------------------------
diff --git a/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/menu/AddRESTTemplateAction.java b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/menu/AddRESTTemplateAction.java
new file mode 100644
index 0000000..96326f6
--- /dev/null
+++ b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/menu/AddRESTTemplateAction.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * Copyright (C) 2007-2009 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.activities.rest.ui.menu;
+
+import java.awt.event.ActionEvent;
+import java.net.URI;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+
+import net.sf.taverna.t2.activities.rest.ui.servicedescription.GenericRESTTemplateService;
+import net.sf.taverna.t2.ui.menu.AbstractContextualMenuAction;
+import net.sf.taverna.t2.ui.menu.MenuManager;
+import net.sf.taverna.t2.workbench.activityicons.ActivityIconManager;
+import net.sf.taverna.t2.workbench.edits.EditManager;
+import net.sf.taverna.t2.workbench.selection.SelectionManager;
+import net.sf.taverna.t2.workbench.ui.workflowview.WorkflowView;
+import uk.org.taverna.commons.services.ServiceRegistry;
+import uk.org.taverna.scufl2.api.core.Workflow;
+
+/**
+ * An action to add a REST activity + a wrapping processor to the workflow.
+ *
+ * @author Alex Nenadic
+ * @author David Withers
+ */
+@SuppressWarnings("serial")
+public class AddRESTTemplateAction extends AbstractContextualMenuAction {
+
+	private static final String ADD_REST = "REST";
+
+	private static final URI insertSection = URI
+			.create("http://taverna.sf.net/2009/contextMenu/insert");
+
+	private EditManager editManager;
+	private MenuManager menuManager;
+	private SelectionManager selectionManager;
+	private ActivityIconManager activityIconManager;
+	private ServiceRegistry serviceRegistry;
+
+	public AddRESTTemplateAction() {
+		super(insertSection, 500);
+	}
+
+	@Override
+	public boolean isEnabled() {
+		return super.isEnabled() && getContextualSelection().getSelection() instanceof Workflow;
+	}
+
+	@Override
+	protected Action createAction() {
+
+		return new AddRestAction();
+	}
+
+	protected class AddRestAction extends AbstractAction {
+		AddRestAction() {
+			super(ADD_REST, activityIconManager
+					.iconForActivity(GenericRESTTemplateService.ACTIVITY_TYPE));
+		}
+
+		public void actionPerformed(ActionEvent e) {
+			WorkflowView.importServiceDescription(
+					GenericRESTTemplateService.getServiceDescription(), false, editManager,
+					menuManager, selectionManager, serviceRegistry);
+		}
+	}
+
+	public void setEditManager(EditManager editManager) {
+		this.editManager = editManager;
+	}
+
+	public void setMenuManager(MenuManager menuManager) {
+		this.menuManager = menuManager;
+	}
+
+	public void setSelectionManager(SelectionManager selectionManager) {
+		this.selectionManager = selectionManager;
+	}
+
+	public void setActivityIconManager(ActivityIconManager activityIconManager) {
+		this.activityIconManager = activityIconManager;
+	}
+
+	public void setServiceRegistry(ServiceRegistry serviceRegistry) {
+		this.serviceRegistry = serviceRegistry;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/11c47f2b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/menu/AddRESTTemplateMenuAction.java
----------------------------------------------------------------------
diff --git a/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/menu/AddRESTTemplateMenuAction.java b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/menu/AddRESTTemplateMenuAction.java
new file mode 100644
index 0000000..ec738e2
--- /dev/null
+++ b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/menu/AddRESTTemplateMenuAction.java
@@ -0,0 +1,114 @@
+/*******************************************************************************
+ * Copyright (C) 2007-2009 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.activities.rest.ui.menu;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.net.URI;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.KeyStroke;
+
+import net.sf.taverna.t2.activities.rest.ui.servicedescription.GenericRESTTemplateService;
+import net.sf.taverna.t2.ui.menu.AbstractMenuAction;
+import net.sf.taverna.t2.ui.menu.DesignOnlyAction;
+import net.sf.taverna.t2.ui.menu.MenuManager;
+import net.sf.taverna.t2.workbench.activityicons.ActivityIconManager;
+import net.sf.taverna.t2.workbench.edits.EditManager;
+import net.sf.taverna.t2.workbench.selection.SelectionManager;
+import net.sf.taverna.t2.workbench.ui.workflowview.WorkflowView;
+import uk.org.taverna.commons.services.ServiceRegistry;
+
+/**
+ * An action to add a REST activity + a wrapping processor to the workflow.
+ *
+ * @author Alex Nenadic
+ * @author alanrw
+ * @author David Withers
+ */
+@SuppressWarnings("serial")
+public class AddRESTTemplateMenuAction extends AbstractMenuAction {
+
+	private static final String ADD_REST = "REST";
+
+	private static final URI INSERT = URI
+			.create("http://taverna.sf.net/2008/t2workbench/menu#insert");
+
+	private static final URI ADD_REST_URI = URI
+			.create("http://taverna.sf.net/2008/t2workbench/menu#graphMenuAddREST");
+
+	private EditManager editManager;
+	private MenuManager menuManager;
+	private SelectionManager selectionManager;
+	private ActivityIconManager activityIconManager;
+	private ServiceRegistry serviceRegistry;
+
+	public AddRESTTemplateMenuAction() {
+		super(INSERT, 500, ADD_REST_URI);
+	}
+
+	@Override
+	protected Action createAction() {
+		return new AddRESTMenuAction();
+	}
+
+	protected class AddRESTMenuAction extends AbstractAction implements DesignOnlyAction {
+		AddRESTMenuAction() {
+			super();
+			putValue(SMALL_ICON, activityIconManager.iconForActivity(GenericRESTTemplateService.ACTIVITY_TYPE));
+			putValue(NAME, ADD_REST);
+			putValue(SHORT_DESCRIPTION, "REST service");
+			putValue(
+					Action.ACCELERATOR_KEY,
+					KeyStroke.getKeyStroke(KeyEvent.VK_H, InputEvent.SHIFT_DOWN_MASK
+							| InputEvent.ALT_DOWN_MASK));
+		}
+
+		public void actionPerformed(ActionEvent e) {
+			WorkflowView.importServiceDescription(
+					GenericRESTTemplateService.getServiceDescription(), false, editManager,
+					menuManager, selectionManager, serviceRegistry);
+		}
+	}
+
+	public void setEditManager(EditManager editManager) {
+		this.editManager = editManager;
+	}
+
+	public void setMenuManager(MenuManager menuManager) {
+		this.menuManager = menuManager;
+	}
+
+	public void setSelectionManager(SelectionManager selectionManager) {
+		this.selectionManager = selectionManager;
+	}
+
+	public void setActivityIconManager(ActivityIconManager activityIconManager) {
+		this.activityIconManager = activityIconManager;
+	}
+
+	public void setServiceRegistry(ServiceRegistry serviceRegistry) {
+		this.serviceRegistry = serviceRegistry;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/11c47f2b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/servicedescription/GenericRESTTemplateService.java
----------------------------------------------------------------------
diff --git a/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/servicedescription/GenericRESTTemplateService.java b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/servicedescription/GenericRESTTemplateService.java
new file mode 100644
index 0000000..69a3b96
--- /dev/null
+++ b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/servicedescription/GenericRESTTemplateService.java
@@ -0,0 +1,76 @@
+package net.sf.taverna.t2.activities.rest.ui.servicedescription;
+
+import java.net.URI;
+
+import javax.swing.Icon;
+
+import net.sf.taverna.t2.activities.rest.RESTActivity;
+import net.sf.taverna.t2.servicedescriptions.AbstractTemplateService;
+import net.sf.taverna.t2.servicedescriptions.ServiceDescription;
+import uk.org.taverna.scufl2.api.configurations.Configuration;
+
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * @author Sergejs Aleksejevs
+ * @author David Withers
+ */
+public class GenericRESTTemplateService extends AbstractTemplateService {
+
+	public static final URI ACTIVITY_TYPE = URI.create("http://ns.taverna.org.uk/2010/activity/rest");
+
+	private static final String REST = "REST";
+
+	@Override
+	public URI getActivityType() {
+		return ACTIVITY_TYPE;
+	}
+
+	@Override
+	public Configuration getActivityConfiguration() {
+		Configuration configuration = new Configuration();
+		configuration.setType(ACTIVITY_TYPE.resolve("#Config"));
+		ObjectNode json = (ObjectNode) configuration.getJson();
+		ObjectNode requestNode = json.objectNode();
+
+		requestNode.put("httpMethod", RESTActivity.HTTP_METHOD.GET.name());
+		requestNode.put("absoluteURITemplate", "http://www.uniprot.org/uniprot/{id}.xml");
+
+		ArrayNode headersNode = requestNode.arrayNode();
+		headersNode.addObject().put("header", "Accept").put("value", "application/xml");
+		headersNode.addObject().put("header", "Content-Type").put("value", "application/xml");
+
+		requestNode.set("headers", headersNode);
+		json.set("request", requestNode);
+		json.put("outgoingDataFormat", RESTActivity.DATA_FORMAT.String.name());
+		json.put("showRedirectionOutputPort", false);
+		json.put("showActualURLPort", false);
+		json.put("showResponseHeadersPort", false);
+		json.put("escapeParameters", true);
+		return configuration;
+	}
+
+	@Override
+	public Icon getIcon() {
+		return RESTActivityIcon.getRESTActivityIcon();
+	}
+
+	public String getName() {
+		return REST;
+	}
+
+	public String getDescription() {
+		return "A generic REST service that can handle all HTTP methods";
+	}
+
+	public static ServiceDescription getServiceDescription() {
+		GenericRESTTemplateService gts = new GenericRESTTemplateService();
+		return gts.templateService;
+	}
+
+	public String getId() {
+		return "http://www.taverna.org.uk/2010/services/rest";
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/11c47f2b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/servicedescription/RESTActivityIcon.java
----------------------------------------------------------------------
diff --git a/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/servicedescription/RESTActivityIcon.java b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/servicedescription/RESTActivityIcon.java
new file mode 100644
index 0000000..c2309a9
--- /dev/null
+++ b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/servicedescription/RESTActivityIcon.java
@@ -0,0 +1,54 @@
+package net.sf.taverna.t2.activities.rest.ui.servicedescription;
+
+import java.awt.Color;
+import java.net.URI;
+
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+
+import net.sf.taverna.t2.workbench.activityicons.ActivityIconSPI;
+import net.sf.taverna.t2.workbench.configuration.colour.ColourManager;
+
+/**
+ *
+ * @author Sergejs Aleksejevs
+ * @author David Withers
+ */
+public class RESTActivityIcon implements ActivityIconSPI {
+	private static final Color PROCESSOR_COLOUR = Color.decode("#7AAFFF");
+
+	private static ImageIcon icon;
+
+	public int canProvideIconScore(URI activityType) {
+		if (GenericRESTTemplateService.ACTIVITY_TYPE.equals(activityType))
+			return DEFAULT_ICON + 1;
+		else
+			return NO_ICON;
+	}
+
+	public Icon getIcon(URI activityType) {
+		return getRESTActivityIcon();
+	}
+
+	public static Icon getRESTActivityIcon() {
+		if (icon == null) {
+			synchronized (RESTActivityIcon.class) {
+				if (icon == null) {
+					try {
+						icon = new ImageIcon(
+								RESTActivityIcon.class.getResource("service_type_rest.png"));
+					} catch (NullPointerException e) {
+						/* icon wasn't found - do nothing, but no icon will be available */
+					}
+				}
+			}
+		}
+		return (icon);
+	}
+
+	public void setColourManager(ColourManager colourManager) {
+		// set colour for REST processors in the workflow diagram
+		colourManager.setPreferredColour(GenericRESTTemplateService.ACTIVITY_TYPE.toString(), PROCESSOR_COLOUR);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/11c47f2b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/serviceprovider/ExampleServiceDesc.java.bak
----------------------------------------------------------------------
diff --git a/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/serviceprovider/ExampleServiceDesc.java.bak b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/serviceprovider/ExampleServiceDesc.java.bak
new file mode 100644
index 0000000..5d9848d
--- /dev/null
+++ b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/serviceprovider/ExampleServiceDesc.java.bak
@@ -0,0 +1,99 @@
+package net.sf.taverna.t2.activities.rest.ui.serviceprovider;
+
+import java.net.URI;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+
+import net.sf.taverna.t2.servicedescriptions.ServiceDescription;
+import net.sf.taverna.t2.workflowmodel.processor.activity.Activity;
+
+import net.sf.taverna.t2.activities.rest.RESTActivity;
+import net.sf.taverna.t2.activities.rest.RESTActivityConfigurationBean;
+
+public class ExampleServiceDesc extends ServiceDescription<RESTActivityConfigurationBean>
+{
+	/**
+	 * The subclass of Activity which should be instantiated when adding a service
+	 * for this description 
+	 */
+	@Override
+	public Class<? extends Activity<RESTActivityConfigurationBean>> getActivityClass() {
+		return RESTActivity.class;
+	}
+
+	/**
+	 * The configuration bean which is to be used for configuring the instantiated activity.
+	 * Making this bean will typically require some of the fields set on this service
+	 * description, like an endpoint URL or method name. 
+	 * 
+	 */
+	@Override
+	public RESTActivityConfigurationBean getActivityConfiguration() {
+		RESTActivityConfigurationBean bean = new RESTActivityConfigurationBean();
+		bean.setExampleString(exampleString);
+		bean.setExampleUri(exampleUri);
+		return bean;
+	}
+
+	/**
+	 * An icon to represent this service description in the service palette.
+	 */
+	@Override
+	public Icon getIcon() {
+	  return null;
+	}
+
+	/**
+	 * The display name that will be shown in service palette and will
+	 * be used as a template for processor name when added to workflow.
+	 */
+	@Override
+	public String getName() {
+		return exampleString;
+	}
+
+	/**
+	 * The path to this service description in the service palette. Folders
+	 * will be created for each element of the returned path.
+	 */
+	@Override
+	public List<String> getPath() {
+		// For deeper paths you may return several strings
+		return Arrays.asList("Service templates", "Examples " + exampleUri);
+	}
+
+	/**
+	 * Return a list of data values uniquely identifying this service
+	 * description (to avoid duplicates). Include only primary key like fields,
+	 * ie. ignore descriptions, icons, etc.
+	 */
+	@Override
+	protected List<? extends Object> getIdentifyingData() {
+		// FIXME: Use your fields instead of example fields
+		return Arrays.<Object>asList(exampleString, exampleUri);
+	}
+
+	
+	// FIXME: Replace example fields and getters/setters with any required
+	// and optional fields. (All fields are searchable in the Service palette,
+	// for instance try a search for exampleString:3)
+	private String exampleString;
+	private URI exampleUri;
+	public String getExampleString() {
+		return exampleString;
+	}
+	public URI getExampleUri() {
+		return exampleUri;
+	}
+	public void setExampleString(String exampleString) {
+		this.exampleString = exampleString;
+	}
+	public void setExampleUri(URI exampleUri) {
+		this.exampleUri = exampleUri;
+	}
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/11c47f2b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/serviceprovider/ExampleServiceProvider.java.bak
----------------------------------------------------------------------
diff --git a/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/serviceprovider/ExampleServiceProvider.java.bak b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/serviceprovider/ExampleServiceProvider.java.bak
new file mode 100644
index 0000000..ff11dbe
--- /dev/null
+++ b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/serviceprovider/ExampleServiceProvider.java.bak
@@ -0,0 +1,106 @@
+package net.sf.taverna.t2.activities.rest.ui.serviceprovider;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+import javax.swing.JOptionPane;
+
+import net.sf.taverna.t2.servicedescriptions.AbstractConfigurableServiceProvider;
+import net.sf.taverna.t2.servicedescriptions.ConfigurableServiceProvider;
+import net.sf.taverna.t2.servicedescriptions.ServiceDescription;
+import net.sf.taverna.t2.servicedescriptions.ServiceDescriptionProvider;
+import net.sf.taverna.t2.workflowmodel.ConfigurationException;
+
+public class ExampleServiceProvider extends AbstractConfigurableServiceProvider<ExampleServiceProviderConfig>
+                                    implements ConfigurableServiceProvider<ExampleServiceProviderConfig>
+{
+	public ExampleServiceProvider()
+	{
+    super(new ExampleServiceProviderConfig());
+  }
+
+  /**
+	 * Do the actual search for services. Return using the callBack parameter.
+	 */
+	@SuppressWarnings("unchecked")
+	public void findServiceDescriptionsAsync(
+			FindServiceDescriptionsCallBack callBack) {
+		// Use callback.status() for long-running searches
+		// callBack.status("Resolving example services");
+
+		List<ServiceDescription> results = new ArrayList<ServiceDescription>();
+
+		// FIXME: Implement the actual service search/lookup instead
+		// of dummy for-loop
+		for (int i = 1; i <= getConfiguration().getNumberOfServices(); i++) {
+			ExampleServiceDesc service = new ExampleServiceDesc();
+			// Populate the service description bean
+			service.setExampleString("Example " + i);
+			service.setExampleUri(getConfiguration().getUri());
+
+			// Optional: set description
+			service.setDescription("Service example number " + i);
+			results.add(service);
+		}
+		
+		// partialResults() can also be called several times from inside
+		// for-loop if the full search takes a long time
+		callBack.partialResults(results);
+
+		// No more results will be coming
+		callBack.finished();
+	}
+	
+	
+//	@Override
+//	/**
+//	 * This allows to have a few configured service providers in the Service Panel at startup;
+//	 * useful if there are some prototypical ones that are useful + need to allow users to add their own
+//	 * through manual config.
+//	 */
+//	public List<ExampleServiceProviderConfig> getDefaultConfigurations() {
+//	  ExampleServiceProviderConfig a = new ExampleServiceProviderConfig();
+//	  a.setUri(URI.create("http://localhost:8181/serviceA"));
+//	  ExampleServiceProviderConfig b = new ExampleServiceProviderConfig();
+//	  b.setUri(URI.create("http://fish.com/serviceB"));
+//	  b.setNumberOfServices(2);
+//	  return Arrays.asList(a, b);
+//	}
+
+	
+
+	/**
+	 * Icon for service provider
+	 */
+	public Icon getIcon() {
+		return null;
+	}
+
+	
+	/**
+	 * Appears in "Import new services..." in Service Panel
+	 */
+	public String getName() {
+		return "My example service";
+	}
+	
+	@Override
+	/**
+   * Name of service provider, appears in right click for 'Remove service
+   * provider'
+   */
+	public String toString() {
+		return getName() + " " + getConfiguration().getUri();
+	}
+
+  @Override
+  protected List<? extends Object> getIdentifyingData() {
+    return Arrays.asList(getConfiguration().getUri());
+  }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/11c47f2b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/serviceprovider/ExampleServiceProviderConfig.java.bak
----------------------------------------------------------------------
diff --git a/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/serviceprovider/ExampleServiceProviderConfig.java.bak b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/serviceprovider/ExampleServiceProviderConfig.java.bak
new file mode 100644
index 0000000..22d8546
--- /dev/null
+++ b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/serviceprovider/ExampleServiceProviderConfig.java.bak
@@ -0,0 +1,31 @@
+package net.sf.taverna.t2.activities.rest.ui.serviceprovider;
+
+import java.net.URI;
+
+import net.sf.taverna.t2.lang.beans.PropertyAnnotated;
+import net.sf.taverna.t2.lang.beans.PropertyAnnotation;
+
+public class ExampleServiceProviderConfig extends PropertyAnnotated
+{
+  private URI uri = URI.create("http://www.example.com");
+  private int numberOfServices = 5;
+  
+  @PropertyAnnotation(displayName="Provider URI", preferred=true)
+  public URI getUri() {
+    return uri;
+  }
+  
+  public void setUri(URI uri) {
+    this.uri = uri;
+  }
+  
+  @PropertyAnnotation(displayName="Number of services")
+  public int getNumberOfServices() {
+    return numberOfServices;
+  }
+  
+  public void setNumberOfServices(int numberOfServices) {
+    this.numberOfServices = numberOfServices;
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/11c47f2b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/view/ConfigureRESTActivityMenuAction.java
----------------------------------------------------------------------
diff --git a/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/view/ConfigureRESTActivityMenuAction.java b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/view/ConfigureRESTActivityMenuAction.java
new file mode 100644
index 0000000..91e198f
--- /dev/null
+++ b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/view/ConfigureRESTActivityMenuAction.java
@@ -0,0 +1,66 @@
+package net.sf.taverna.t2.activities.rest.ui.view;
+
+import javax.swing.Action;
+
+import uk.org.taverna.commons.services.ServiceRegistry;
+
+import net.sf.taverna.t2.activities.rest.ui.config.RESTActivityConfigureAction;
+import net.sf.taverna.t2.activities.rest.ui.servicedescription.GenericRESTTemplateService;
+import net.sf.taverna.t2.servicedescriptions.ServiceDescriptionRegistry;
+import net.sf.taverna.t2.workbench.activityicons.ActivityIconManager;
+import net.sf.taverna.t2.workbench.activitytools.AbstractConfigureActivityMenuAction;
+import net.sf.taverna.t2.workbench.edits.EditManager;
+import net.sf.taverna.t2.workbench.file.FileManager;
+
+/**
+ * This action is responsible for enabling the contextual menu entry on processors that perform
+ * RESTActivity'ies.
+ * NB! As a side-effect this also enables the pop-up with for configuration of the processor when it
+ * is added to the workflow from the Service Panel.
+ *
+ * @author Sergejs Aleksejevs
+ * @author David Withers
+ */
+public class ConfigureRESTActivityMenuAction extends AbstractConfigureActivityMenuAction {
+
+	private EditManager editManager;
+	private FileManager fileManager;
+	private ActivityIconManager activityIconManager;
+	private ServiceDescriptionRegistry serviceDescriptionRegistry;
+	private ServiceRegistry serviceRegistry;
+
+	public ConfigureRESTActivityMenuAction() {
+		super(GenericRESTTemplateService.ACTIVITY_TYPE);
+	}
+
+	@Override
+	protected Action createAction() {
+		RESTActivityConfigureAction configAction = new RESTActivityConfigureAction(findActivity(),
+				getParentFrame(), editManager, fileManager, activityIconManager,
+				serviceDescriptionRegistry, serviceRegistry);
+		configAction.putValue(Action.NAME, "Configure REST service");
+		addMenuDots(configAction);
+		return configAction;
+	}
+
+	public void setEditManager(EditManager editManager) {
+		this.editManager = editManager;
+	}
+
+	public void setFileManager(FileManager fileManager) {
+		this.fileManager = fileManager;
+	}
+
+	public void setActivityIconManager(ActivityIconManager activityIconManager) {
+		this.activityIconManager = activityIconManager;
+	}
+
+	public void setServiceDescriptionRegistry(ServiceDescriptionRegistry serviceDescriptionRegistry) {
+		this.serviceDescriptionRegistry = serviceDescriptionRegistry;
+	}
+
+	public void setServiceRegistry(ServiceRegistry serviceRegistry) {
+		this.serviceRegistry = serviceRegistry;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/11c47f2b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/view/RESTActivityMainContextViewFactory.java
----------------------------------------------------------------------
diff --git a/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/view/RESTActivityMainContextViewFactory.java b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/view/RESTActivityMainContextViewFactory.java
new file mode 100644
index 0000000..5bea949
--- /dev/null
+++ b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/view/RESTActivityMainContextViewFactory.java
@@ -0,0 +1,62 @@
+package net.sf.taverna.t2.activities.rest.ui.view;
+
+import java.util.Arrays;
+import java.util.List;
+
+import net.sf.taverna.t2.activities.rest.ui.servicedescription.GenericRESTTemplateService;
+import net.sf.taverna.t2.servicedescriptions.ServiceDescriptionRegistry;
+import net.sf.taverna.t2.workbench.activityicons.ActivityIconManager;
+import net.sf.taverna.t2.workbench.configuration.colour.ColourManager;
+import net.sf.taverna.t2.workbench.edits.EditManager;
+import net.sf.taverna.t2.workbench.file.FileManager;
+import net.sf.taverna.t2.workbench.ui.views.contextualviews.ContextualView;
+import net.sf.taverna.t2.workbench.ui.views.contextualviews.activity.ContextualViewFactory;
+import uk.org.taverna.commons.services.ServiceRegistry;
+import uk.org.taverna.scufl2.api.activity.Activity;
+
+public class RESTActivityMainContextViewFactory implements ContextualViewFactory<Activity> {
+
+	private EditManager editManager;
+	private FileManager fileManager;
+	private ActivityIconManager activityIconManager;
+	private ColourManager colourManager;
+	private ServiceDescriptionRegistry serviceDescriptionRegistry;
+	private ServiceRegistry serviceRegistry;
+
+	public boolean canHandle(Object selection) {
+		return selection instanceof Activity
+				&& ((Activity) selection).getType()
+						.equals(GenericRESTTemplateService.ACTIVITY_TYPE);
+	}
+
+	public List<ContextualView> getViews(Activity selection) {
+		return Arrays.<ContextualView> asList(new RESTActivityMainContextualView(selection,
+				editManager, fileManager, activityIconManager, colourManager,
+				serviceDescriptionRegistry, serviceRegistry));
+	}
+
+	public void setEditManager(EditManager editManager) {
+		this.editManager = editManager;
+	}
+
+	public void setFileManager(FileManager fileManager) {
+		this.fileManager = fileManager;
+	}
+
+	public void setActivityIconManager(ActivityIconManager activityIconManager) {
+		this.activityIconManager = activityIconManager;
+	}
+
+	public void setColourManager(ColourManager colourManager) {
+		this.colourManager = colourManager;
+	}
+
+	public void setServiceDescriptionRegistry(ServiceDescriptionRegistry serviceDescriptionRegistry) {
+		this.serviceDescriptionRegistry = serviceDescriptionRegistry;
+	}
+
+	public void setServiceRegistry(ServiceRegistry serviceRegistry) {
+		this.serviceRegistry = serviceRegistry;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/11c47f2b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/view/RESTActivityMainContextualView.java
----------------------------------------------------------------------
diff --git a/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/view/RESTActivityMainContextualView.java b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/view/RESTActivityMainContextualView.java
new file mode 100644
index 0000000..f4ffe0f
--- /dev/null
+++ b/taverna-rest-activity-ui/src/main/java/net/sf/taverna/t2/activities/rest/ui/view/RESTActivityMainContextualView.java
@@ -0,0 +1,220 @@
+package net.sf.taverna.t2.activities.rest.ui.view;
+
+import java.awt.Font;
+import java.awt.Frame;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+
+import javax.swing.Action;
+import javax.swing.BorderFactory;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+
+import net.sf.taverna.t2.activities.rest.RESTActivity;
+import net.sf.taverna.t2.activities.rest.RESTActivity.HTTP_METHOD;
+import net.sf.taverna.t2.activities.rest.RESTActivityConfigurationBean;
+import net.sf.taverna.t2.activities.rest.ui.config.RESTActivityConfigureAction;
+import net.sf.taverna.t2.servicedescriptions.ServiceDescriptionRegistry;
+import net.sf.taverna.t2.workbench.activityicons.ActivityIconManager;
+import net.sf.taverna.t2.workbench.configuration.colour.ColourManager;
+import net.sf.taverna.t2.workbench.edits.EditManager;
+import net.sf.taverna.t2.workbench.file.FileManager;
+import net.sf.taverna.t2.workbench.ui.views.contextualviews.ContextualView;
+import uk.org.taverna.commons.services.ServiceRegistry;
+import uk.org.taverna.scufl2.api.activity.Activity;
+import uk.org.taverna.scufl2.api.common.Scufl2Tools;
+import uk.org.taverna.scufl2.api.configurations.Configuration;
+
+@SuppressWarnings("serial")
+public class RESTActivityMainContextualView extends ContextualView {
+
+	private final Scufl2Tools scufl2Tools = new Scufl2Tools();
+
+	private final Activity activity;
+
+	private JPanel jpMainPanel;
+	private JTextField tfHTTPMethod;
+	private JTextArea taURLSignature;
+	private JTextField tfAcceptHeader;
+	private JLabel jlContentType;
+	private JTextField tfContentTypeHeader;
+	private JLabel jlSendDataAs;
+	private JTextField tfSendDataAs;
+	private JLabel jlSendHTTPExpectRequestHeader;
+	private JTextField tfSendHTTPExpectRequestHeader;
+
+	private final EditManager editManager;
+	private final FileManager fileManager;
+	private final ActivityIconManager activityIconManager;
+	private final ColourManager colourManager;
+	private final ServiceDescriptionRegistry serviceDescriptionRegistry;
+	private final ServiceRegistry serviceRegistry;
+
+	public RESTActivityMainContextualView(Activity activity, EditManager editManager,
+			FileManager fileManager, ActivityIconManager activityIconManager,
+			ColourManager colourManager, ServiceDescriptionRegistry serviceDescriptionRegistry,
+			ServiceRegistry serviceRegistry) {
+		this.activity = activity;
+		this.editManager = editManager;
+		this.fileManager = fileManager;
+		this.activityIconManager = activityIconManager;
+		this.colourManager = colourManager;
+		this.serviceDescriptionRegistry = serviceDescriptionRegistry;
+		this.serviceRegistry = serviceRegistry;
+		initView();
+	}
+
+	@Override
+	public JComponent getMainFrame() {
+		jpMainPanel = new JPanel(new GridBagLayout());
+		jpMainPanel
+				.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(4, 2,
+						4, 2), BorderFactory.createLineBorder(
+						colourManager.getPreferredColour(RESTActivity.class.getCanonicalName()), 2)));
+
+		GridBagConstraints c = new GridBagConstraints();
+		c.fill = GridBagConstraints.HORIZONTAL;
+		c.anchor = GridBagConstraints.WEST;
+		c.weighty = 0;
+
+		c.gridx = 0;
+		c.gridy = 0;
+		c.insets = new Insets(5, 5, 5, 5);
+		JLabel jlHTTPMethod = new JLabel("HTTP Method:");
+		jlHTTPMethod.setFont(jlHTTPMethod.getFont().deriveFont(Font.BOLD));
+		jpMainPanel.add(jlHTTPMethod, c);
+
+		c.gridx++;
+		c.weightx = 1.0;
+		tfHTTPMethod = new JTextField();
+		tfHTTPMethod.setEditable(false);
+		jpMainPanel.add(tfHTTPMethod, c);
+		c.weightx = 0;
+
+		c.gridx = 0;
+		c.gridy++;
+		JLabel jlURLSignature = new JLabel("URL Template:");
+		jlURLSignature.setFont(jlURLSignature.getFont().deriveFont(Font.BOLD));
+		jpMainPanel.add(jlURLSignature, c);
+
+		c.gridx++;
+		taURLSignature = new JTextArea(3, 30);
+		taURLSignature.setEditable(false);
+		taURLSignature.setLineWrap(true);
+		JScrollPane spURLSignature = new JScrollPane(taURLSignature);
+		jpMainPanel.add(spURLSignature, c);
+
+		c.gridx = 0;
+		c.gridy++;
+		JLabel jlAcceptHeader = new JLabel("'Accept' header:");
+		jlAcceptHeader.setFont(jlAcceptHeader.getFont().deriveFont(Font.BOLD));
+		jpMainPanel.add(jlAcceptHeader, c);
+
+		c.gridx++;
+		tfAcceptHeader = new JTextField();
+		tfAcceptHeader.setEditable(false);
+		jpMainPanel.add(tfAcceptHeader, c);
+
+		c.gridx = 0;
+		c.gridy++;
+		jlContentType = new JLabel("'Content-Type' header:");
+		jlContentType.setFont(jlContentType.getFont().deriveFont(Font.BOLD));
+		jlContentType.setVisible(false);
+		jpMainPanel.add(jlContentType, c);
+
+		c.gridx++;
+		tfContentTypeHeader = new JTextField();
+		tfContentTypeHeader.setEditable(false);
+		tfContentTypeHeader.setVisible(false);
+		jpMainPanel.add(tfContentTypeHeader, c);
+
+		c.gridx = 0;
+		c.gridy++;
+		jlSendDataAs = new JLabel("Send data as:");
+		jlSendDataAs.setFont(jlSendDataAs.getFont().deriveFont(Font.BOLD));
+		jlSendDataAs.setVisible(false);
+		jpMainPanel.add(jlSendDataAs, c);
+
+		c.gridx++;
+		tfSendDataAs = new JTextField();
+		tfSendDataAs.setEditable(false);
+		tfSendDataAs.setVisible(false);
+		jpMainPanel.add(tfSendDataAs, c);
+
+		c.gridx = 0;
+		c.gridy++;
+		jlSendHTTPExpectRequestHeader = new JLabel("Send HTTP 'Expect' header:");
+		jlSendHTTPExpectRequestHeader.setFont(jlSendHTTPExpectRequestHeader.getFont().deriveFont(
+				Font.BOLD));
+		jlSendHTTPExpectRequestHeader.setVisible(false);
+		jpMainPanel.add(jlSendHTTPExpectRequestHeader, c);
+
+		c.gridx++;
+		tfSendHTTPExpectRequestHeader = new JTextField();
+		tfSendHTTPExpectRequestHeader.setEditable(false);
+		tfSendHTTPExpectRequestHeader.setVisible(false);
+		jpMainPanel.add(tfSendHTTPExpectRequestHeader, c);
+
+		// populate the view with values
+		refreshView();
+
+		return jpMainPanel;
+	}
+
+	@Override
+	/**
+	 * This is the title of the contextual view - shown in the list of other available
+	 * views (even when this contextual view is collapsed).
+	 */
+	public String getViewTitle() {
+		return "REST Service Details";
+	}
+
+	/**
+	 * Typically called when the activity configuration has changed.
+	 */
+	@Override
+	public void refreshView() {
+		Configuration configuration = scufl2Tools.configurationFor(activity, activity.getParent());
+		RESTActivityConfigurationBean configurationBean = new RESTActivityConfigurationBean(configuration.getJson());
+
+		// toggle visibility of the elements that do not always appear
+		HTTP_METHOD httpMethod = configurationBean.getHttpMethod();
+		jlContentType.setVisible(httpMethod == HTTP_METHOD.POST || httpMethod == HTTP_METHOD.PUT);
+		tfContentTypeHeader.setVisible(httpMethod == HTTP_METHOD.POST || httpMethod == HTTP_METHOD.PUT);
+		jlSendDataAs.setVisible(httpMethod == HTTP_METHOD.POST || httpMethod == HTTP_METHOD.PUT);
+		tfSendDataAs.setVisible(httpMethod == HTTP_METHOD.POST || httpMethod == HTTP_METHOD.PUT);
+		jlSendHTTPExpectRequestHeader.setVisible(httpMethod == HTTP_METHOD.POST || httpMethod == HTTP_METHOD.PUT);
+		tfSendHTTPExpectRequestHeader.setVisible(httpMethod == HTTP_METHOD.POST || httpMethod == HTTP_METHOD.PUT);
+		jpMainPanel.revalidate();
+
+		tfHTTPMethod.setText("" + configurationBean.getHttpMethod());
+		taURLSignature.setText(configurationBean.getUrlSignature());
+		tfAcceptHeader.setText(configurationBean.getAcceptsHeaderValue());
+		tfContentTypeHeader.setText(configurationBean.getContentTypeForUpdates());
+		tfSendDataAs.setText("" + configurationBean.getOutgoingDataFormat());
+		tfSendHTTPExpectRequestHeader.setText("" + configurationBean.getSendHTTPExpectRequestHeader());
+	}
+
+	/**
+	 * View position hint
+	 */
+	@Override
+	public int getPreferredPosition() {
+		// want to be on top, as it's the main contextual view for this activity
+		return 100;
+	}
+
+	@Override
+	public Action getConfigureAction(final Frame owner) {
+		// "Configure" button appears because of this action being returned
+		return new RESTActivityConfigureAction(activity, owner, editManager, fileManager,
+				activityIconManager, serviceDescriptionRegistry, serviceRegistry);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/11c47f2b/taverna-rest-activity-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.servicedescriptions.ServiceDescriptionProvider
----------------------------------------------------------------------
diff --git a/taverna-rest-activity-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.servicedescriptions.ServiceDescriptionProvider b/taverna-rest-activity-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.servicedescriptions.ServiceDescriptionProvider
new file mode 100644
index 0000000..a7222c4
--- /dev/null
+++ b/taverna-rest-activity-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.servicedescriptions.ServiceDescriptionProvider
@@ -0,0 +1 @@
+net.sf.taverna.t2.activities.rest.ui.servicedescription.GenericRESTTemplateService
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/11c47f2b/taverna-rest-activity-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent
----------------------------------------------------------------------
diff --git a/taverna-rest-activity-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent b/taverna-rest-activity-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent
new file mode 100644
index 0000000..a1e5390
--- /dev/null
+++ b/taverna-rest-activity-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent
@@ -0,0 +1,3 @@
+net.sf.taverna.t2.activities.rest.ui.view.ConfigureRESTActivityMenuAction
+net.sf.taverna.t2.activities.rest.ui.menu.AddRESTTemplateAction
+net.sf.taverna.t2.activities.rest.ui.menu.AddRESTTemplateMenuAction
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/11c47f2b/taverna-rest-activity-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.activityicons.ActivityIconSPI
----------------------------------------------------------------------
diff --git a/taverna-rest-activity-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.activityicons.ActivityIconSPI b/taverna-rest-activity-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.activityicons.ActivityIconSPI
new file mode 100644
index 0000000..9440d43
--- /dev/null
+++ b/taverna-rest-activity-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.activityicons.ActivityIconSPI
@@ -0,0 +1 @@
+net.sf.taverna.t2.activities.rest.ui.servicedescription.RESTActivityIcon
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/11c47f2b/taverna-rest-activity-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.views.contextualviews.activity.ContextualViewFactory
----------------------------------------------------------------------
diff --git a/taverna-rest-activity-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.views.contextualviews.activity.ContextualViewFactory b/taverna-rest-activity-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.views.contextualviews.activity.ContextualViewFactory
new file mode 100644
index 0000000..5325bf1
--- /dev/null
+++ b/taverna-rest-activity-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.views.contextualviews.activity.ContextualViewFactory
@@ -0,0 +1 @@
+ net.sf.taverna.t2.activities.rest.ui.view.RESTActivityMainContextViewFactory

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/11c47f2b/taverna-rest-activity-ui/src/main/resources/META-INF/spring/rest-activity-ui-context-osgi.xml
----------------------------------------------------------------------
diff --git a/taverna-rest-activity-ui/src/main/resources/META-INF/spring/rest-activity-ui-context-osgi.xml b/taverna-rest-activity-ui/src/main/resources/META-INF/spring/rest-activity-ui-context-osgi.xml
new file mode 100644
index 0000000..643d5be
--- /dev/null
+++ b/taverna-rest-activity-ui/src/main/resources/META-INF/spring/rest-activity-ui-context-osgi.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans:beans xmlns="http://www.springframework.org/schema/osgi" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:beans="http://www.springframework.org/schema/beans"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans
+                      http://www.springframework.org/schema/beans/spring-beans.xsd
+                      http://www.springframework.org/schema/osgi
+                      http://www.springframework.org/schema/osgi/spring-osgi.xsd">
+
+	<service ref="RESTActivityIcon" interface="net.sf.taverna.t2.workbench.activityicons.ActivityIconSPI" />
+
+	<service ref="GenericRESTTemplateService" interface="net.sf.taverna.t2.servicedescriptions.ServiceDescriptionProvider" />
+
+	<service ref="ConfigureRESTActivityMenuAction" auto-export="interfaces" />
+	<service ref="AddRESTTemplateAction" auto-export="interfaces" />
+	<service ref="AddRESTTemplateMenuAction" auto-export="interfaces" />
+
+	<service ref="RESTActivityMainContextViewFactory" interface="net.sf.taverna.t2.workbench.ui.views.contextualviews.activity.ContextualViewFactory" />
+
+	<reference id="editManager" interface="net.sf.taverna.t2.workbench.edits.EditManager" />
+	<reference id="fileManager" interface="net.sf.taverna.t2.workbench.file.FileManager" />
+	<reference id="menuManager" interface="net.sf.taverna.t2.ui.menu.MenuManager" />
+	<reference id="selectionManager" interface="net.sf.taverna.t2.workbench.selection.SelectionManager" />
+	<reference id="activityIconManager" interface="net.sf.taverna.t2.workbench.activityicons.ActivityIconManager" />
+	<reference id="colourManager" interface="net.sf.taverna.t2.workbench.configuration.colour.ColourManager" />
+	<reference id="serviceDescriptionRegistry" interface="net.sf.taverna.t2.servicedescriptions.ServiceDescriptionRegistry" />
+	<reference id="serviceRegistry" interface="uk.org.taverna.commons.services.ServiceRegistry" />
+
+</beans:beans>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/11c47f2b/taverna-rest-activity-ui/src/main/resources/META-INF/spring/rest-activity-ui-context.xml
----------------------------------------------------------------------
diff --git a/taverna-rest-activity-ui/src/main/resources/META-INF/spring/rest-activity-ui-context.xml b/taverna-rest-activity-ui/src/main/resources/META-INF/spring/rest-activity-ui-context.xml
new file mode 100644
index 0000000..2b699e7
--- /dev/null
+++ b/taverna-rest-activity-ui/src/main/resources/META-INF/spring/rest-activity-ui-context.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans
+                      http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<bean id="RESTActivityIcon"
+		class="net.sf.taverna.t2.activities.rest.ui.servicedescription.RESTActivityIcon">
+		<property name="colourManager" ref="colourManager" />
+	</bean>
+
+	<bean id="GenericRESTTemplateService"
+		class="net.sf.taverna.t2.activities.rest.ui.servicedescription.GenericRESTTemplateService" />
+
+	<bean id="ConfigureRESTActivityMenuAction"
+		class="net.sf.taverna.t2.activities.rest.ui.view.ConfigureRESTActivityMenuAction">
+		<property name="editManager" ref="editManager" />
+		<property name="fileManager" ref="fileManager" />
+		<property name="activityIconManager" ref="activityIconManager" />
+		<property name="serviceDescriptionRegistry" ref="serviceDescriptionRegistry" />
+		<property name="serviceRegistry" ref="serviceRegistry" />
+	</bean>
+	<bean id="AddRESTTemplateAction"
+		class="net.sf.taverna.t2.activities.rest.ui.menu.AddRESTTemplateAction">
+		<property name="editManager" ref="editManager" />
+		<property name="menuManager" ref="menuManager" />
+		<property name="selectionManager" ref="selectionManager" />
+		<property name="activityIconManager" ref="activityIconManager" />
+		<property name="serviceRegistry" ref="serviceRegistry" />
+	</bean>
+	<bean id="AddRESTTemplateMenuAction"
+		class="net.sf.taverna.t2.activities.rest.ui.menu.AddRESTTemplateMenuAction">
+		<property name="editManager" ref="editManager" />
+		<property name="menuManager" ref="menuManager" />
+		<property name="selectionManager" ref="selectionManager" />
+		<property name="activityIconManager" ref="activityIconManager" />
+		<property name="serviceRegistry" ref="serviceRegistry" />
+	</bean>
+
+	<bean id="RESTActivityMainContextViewFactory"
+		class="net.sf.taverna.t2.activities.rest.ui.view.RESTActivityMainContextViewFactory">
+		<property name="editManager" ref="editManager" />
+		<property name="fileManager" ref="fileManager" />
+		<property name="activityIconManager" ref="activityIconManager" />
+		<property name="colourManager" ref="colourManager" />
+		<property name="serviceDescriptionRegistry" ref="serviceDescriptionRegistry" />
+		<property name="serviceRegistry" ref="serviceRegistry" />
+	</bean>
+
+</beans>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/11c47f2b/taverna-rest-activity-ui/src/main/resources/net/sf/taverna/t2/activities/rest/ui/config/information.png
----------------------------------------------------------------------
diff --git a/taverna-rest-activity-ui/src/main/resources/net/sf/taverna/t2/activities/rest/ui/config/information.png b/taverna-rest-activity-ui/src/main/resources/net/sf/taverna/t2/activities/rest/ui/config/information.png
new file mode 100644
index 0000000..12cd1ae
Binary files /dev/null and b/taverna-rest-activity-ui/src/main/resources/net/sf/taverna/t2/activities/rest/ui/config/information.png differ