http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/163747de/taverna-external-tool-activity-ui/src/main/java/net/sf/taverna/t2/activities/externaltool/views/StringReplacementPanel.java
----------------------------------------------------------------------
diff --git 
a/taverna-external-tool-activity-ui/src/main/java/net/sf/taverna/t2/activities/externaltool/views/StringReplacementPanel.java
 
b/taverna-external-tool-activity-ui/src/main/java/net/sf/taverna/t2/activities/externaltool/views/StringReplacementPanel.java
deleted file mode 100644
index 1f85d3a..0000000
--- 
a/taverna-external-tool-activity-ui/src/main/java/net/sf/taverna/t2/activities/externaltool/views/StringReplacementPanel.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/**
- * 
- */
-package net.sf.taverna.t2.activities.externaltool.views;
-
-import java.awt.BorderLayout;
-import java.awt.Color;
-import java.awt.GridBagConstraints;
-import java.awt.GridBagLayout;
-import java.awt.Insets;
-import java.awt.event.ActionEvent;
-import java.util.List;
-
-import javax.swing.AbstractAction;
-import javax.swing.BorderFactory;
-import javax.swing.JButton;
-import javax.swing.JCheckBox;
-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 javax.swing.border.CompoundBorder;
-import javax.swing.border.EmptyBorder;
-
-import 
net.sf.taverna.t2.activities.externaltool.manager.ssh.ExternalToolSshNodeViewer;
-import net.sf.taverna.t2.activities.externaltool.utils.Tools;
-import net.sf.taverna.t2.lang.ui.DeselectingButton;
-
-/**
- * @author alanrw
- *
- */
-public class StringReplacementPanel extends JPanel {
-       
-       private static final String STRING_REPLACEMENT_DESCRIPTION = "You can 
use a string replacement to " +
-       "feed data into the service via an input port and have that data 
replace part of the " +
-       "command.";
-       private final List<ExternalToolStringReplacementViewer> 
stringReplacementViewList;
-       private int stringReplacementGridy = 1;
-       private final ExternalToolConfigView view;
-       
-       private static Insets insets = new Insets(1,5,1,5);
-       
-       private static String[] elementLabels = new String[] {"Taverna port 
name", "Replace port name", "String to replace"};
-       
-       private static CompoundBorder border = 
BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,5,5,5), 
BorderFactory.createLineBorder(Color.BLACK, 1));
-
-       
-       public StringReplacementPanel(final ExternalToolConfigView view, final 
List<ExternalToolStringReplacementViewer> stringReplacementViewList) {
-               super(new BorderLayout());
-               this.view = view;
-               this.stringReplacementViewList = stringReplacementViewList;
-
-               final JPanel inputEditPanel = new JPanel(new GridBagLayout());
-
-               final GridBagConstraints inputConstraint = new 
GridBagConstraints();
-
-               inputConstraint.anchor = GridBagConstraints.FIRST_LINE_START;
-               inputConstraint.gridx = 0;
-               inputConstraint.gridy = 0;
-               inputConstraint.weightx = 0.1;
-               inputConstraint.fill = GridBagConstraints.BOTH;
-
-               inputConstraint.gridx = 0;
-               synchronized (stringReplacementViewList) {
-                       for (ExternalToolStringReplacementViewer inputView : 
stringReplacementViewList) {
-                               addStringReplacementViewer(this, inputEditPanel,
-                                               inputView, elementLabels);
-
-                       }
-               }
-
-               JTextArea descriptionText = new JTextArea(
-                               STRING_REPLACEMENT_DESCRIPTION);
-               descriptionText.setEditable(false);
-               descriptionText.setFocusable(false);
-               descriptionText.setBorder(new EmptyBorder(5, 5, 10, 5));
-               descriptionText.setLineWrap(true);
-               descriptionText.setWrapStyleWord(true);
-
-               this.add(descriptionText, BorderLayout.NORTH);
-               this.add(new JScrollPane(inputEditPanel),
-                               BorderLayout.CENTER);
-               JButton addInputPortButton = new DeselectingButton("Add string 
replacement",
-                               new AbstractAction() {
-
-                       public void actionPerformed(ActionEvent e) {
-
-                               int portNumber = 1;
-                               String name2 = "in" + portNumber++;
-                               boolean nameExists = true;
-                               while (nameExists == true) {
-                                       nameExists = view.portNameExists(name2);
-                                       if (nameExists) {
-                                               name2 = "in" + portNumber++;
-                                       }
-                               }
-
-                               ExternalToolStringReplacementViewer newViewer = 
new ExternalToolStringReplacementViewer(
-                                               name2);
-                               synchronized (stringReplacementViewList) {
-                                       
stringReplacementViewList.add(newViewer);
-                                       
addStringReplacementViewer(StringReplacementPanel.this, inputEditPanel,
-                                                       newViewer, 
elementLabels);
-                                       inputEditPanel.revalidate();
-                                       inputEditPanel.repaint();
-                               }
-
-                       }
-
-               });
-
-               JPanel buttonPanel = new JPanel();
-               buttonPanel.setLayout(new BorderLayout());
-
-               buttonPanel.add(addInputPortButton, BorderLayout.EAST);
-
-               this.add(buttonPanel, BorderLayout.SOUTH);
-       }
-       
-       private void addStringReplacementViewer(final JPanel outerPanel,
-                       final JPanel innerPanel, final 
ExternalToolStringReplacementViewer viewer, String[] elementLabels) {
-               Tools.addViewer(innerPanel,
-                               elementLabels,
-                               new JComponent[] {viewer.getNameField(), 
viewer.getValueFromField(), viewer.getValueField()},
-                               stringReplacementViewList,
-                               viewer,
-                               outerPanel);
-       }
-
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/163747de/taverna-external-tool-activity-ui/src/main/java/net/sf/taverna/t2/activities/externaltool/views/ToolXMLPanel.java
----------------------------------------------------------------------
diff --git 
a/taverna-external-tool-activity-ui/src/main/java/net/sf/taverna/t2/activities/externaltool/views/ToolXMLPanel.java
 
b/taverna-external-tool-activity-ui/src/main/java/net/sf/taverna/t2/activities/externaltool/views/ToolXMLPanel.java
deleted file mode 100644
index b49211f..0000000
--- 
a/taverna-external-tool-activity-ui/src/main/java/net/sf/taverna/t2/activities/externaltool/views/ToolXMLPanel.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/**
- * 
- */
-package net.sf.taverna.t2.activities.externaltool.views;
-
-import java.awt.BorderLayout;
-
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-
-import net.sf.taverna.t2.renderers.impl.XMLTree;
-
-import de.uni_luebeck.inb.knowarc.usecases.UseCaseDescription;
-
-/**
- * @author alanrw
- *
- */
-public class ToolXMLPanel extends JPanel {
-
-       public ToolXMLPanel(UseCaseDescription useCaseDescription) {
-               super(new BorderLayout());
-               XMLTree xmlTree = new 
XMLTree(useCaseDescription.writeToXMLElement());
-               this.add(new JScrollPane(xmlTree), BorderLayout.CENTER);
-       }
-
-       public void regenerateTree(UseCaseDescription useCaseDescription) {
-               this.removeAll();
-               XMLTree xmlTree = new 
XMLTree(useCaseDescription.writeToXMLElement());
-               this.add(new JScrollPane(xmlTree), BorderLayout.CENTER);        
        
-       }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/163747de/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/actions/ExternalToolActivityConfigureAction.java
----------------------------------------------------------------------
diff --git 
a/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/actions/ExternalToolActivityConfigureAction.java
 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/actions/ExternalToolActivityConfigureAction.java
new file mode 100644
index 0000000..2e8d981
--- /dev/null
+++ 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/actions/ExternalToolActivityConfigureAction.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (C) 2009 Hajo Nils Krabbenhoeft, INB, University of Luebeck
+ * modified 2010 Hajo Nils Krabbenhoeft, spratpix GmbH & Co. KG
+ *
+ *  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 org.apache.taverna.activities.externaltool.actions;
+
+import java.awt.Frame;
+import java.awt.event.ActionEvent;
+
+import javax.swing.Action;
+
+import org.apache.taverna.activities.externaltool.ExternalToolActivity;
+import 
org.apache.taverna.activities.externaltool.ExternalToolActivityConfigurationBean;
+import org.apache.taverna.activities.externaltool.views.ExternalToolConfigView;
+import org.apache.taverna.workbench.activityicons.ActivityIconManager;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.file.FileManager;
+import 
org.apache.taverna.workbench.ui.actions.activity.ActivityConfigurationAction;
+import 
org.apache.taverna.workbench.ui.views.contextualviews.activity.ActivityConfigurationDialog;
+
+/**
+ * This class implements an ActivityConfigurationAction to configure the 
ExternalToolActivity
+ * plugin. The configuration action is called "Configure UseCase invocation" 
and is implemented in
+ * the KnowARCConfigurationDialog inside the knowarc-usecases maven artifact.
+ *
+ * @author Hajo Nils Krabbenhoeft
+ */
+@SuppressWarnings("serial")
+public class ExternalToolActivityConfigureAction extends
+               ActivityConfigurationAction {// <ExternalToolActivity, 
ExternalToolActivityConfigurationBean> {
+
+       private final Frame owner;
+       private final EditManager editManager;
+       private final FileManager fileManager;
+
+       public ExternalToolActivityConfigureAction(ExternalToolActivity 
activity, Frame owner,
+                       EditManager editManager, FileManager fileManager, 
ActivityIconManager activityIconManager) {
+               super(activity, activityIconManager);
+               this.editManager = editManager;
+               this.fileManager = fileManager;
+               putValue(Action.NAME, "Configure tool invocation");
+               this.owner = owner;
+       }
+
+       public void actionPerformed(ActionEvent e) {
+               /*
+                * if (getActivity().getConfiguration() instanceof
+                * RegisteredExternalToolActivityConfigurationBean) { new 
KnowARCConfigurationDialog(owner,
+                * false, 
KnowARCConfigurationFactory.getConfiguration()).setVisible(true); } else
+                */{
+                       ActivityConfigurationDialog currentDialog = 
ActivityConfigurationAction
+                                       .getDialog(getActivity());
+                       if (currentDialog != null) {
+                               currentDialog.toFront();
+                               return;
+                       }
+                       final ExternalToolConfigView externalToolConfigView = 
new ExternalToolConfigView(
+                                       (ExternalToolActivity) getActivity());
+                       final ActivityConfigurationDialog<ExternalToolActivity, 
ExternalToolActivityConfigurationBean> dialog = new 
ActivityConfigurationDialog<ExternalToolActivity, 
ExternalToolActivityConfigurationBean>(
+                                       getActivity(), externalToolConfigView, 
editManager, fileManager);
+
+                       ActivityConfigurationAction.setDialog(getActivity(), 
dialog, fileManager);
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/163747de/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/configuration/ToolInvocationConfiguration.java
----------------------------------------------------------------------
diff --git 
a/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/configuration/ToolInvocationConfiguration.java
 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/configuration/ToolInvocationConfiguration.java
new file mode 100644
index 0000000..67f8f4b
--- /dev/null
+++ 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/configuration/ToolInvocationConfiguration.java
@@ -0,0 +1,57 @@
+/**
+ *
+ */
+package org.apache.taverna.activities.externaltool.configuration;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import uk.org.taverna.configuration.AbstractConfigurable;
+
+
+/**
+ * @author alanrw
+ *
+ */
+public class ToolInvocationConfiguration extends AbstractConfigurable {
+
+       private static ToolInvocationConfiguration instance;
+
+       private Map<String, String> defaultPropertyMap;
+
+       public static ToolInvocationConfiguration getInstance() {
+               if (instance == null) {
+                       instance = new ToolInvocationConfiguration();
+               }
+               return instance;
+       }
+
+       @Override
+       public String getCategory() {
+               return "general";
+       }
+
+       @Override
+       public Map<String, String> getDefaultPropertyMap() {
+               if (defaultPropertyMap == null) {
+                       defaultPropertyMap = new HashMap<String, String>();
+               }
+               return defaultPropertyMap;
+       }
+
+       @Override
+       public String getDisplayName() {
+               return "Tool invocation";
+       }
+
+       @Override
+       public String getFilePrefix() {
+               return "ToolInvocation";
+       }
+
+       @Override
+       public String getUUID() {
+               return "B611F5C2-EB49-479E-B01A-7F3F56E6918A";
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/163747de/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/GroupPanel.java
----------------------------------------------------------------------
diff --git 
a/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/GroupPanel.java
 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/GroupPanel.java
new file mode 100644
index 0000000..46710e1
--- /dev/null
+++ 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/GroupPanel.java
@@ -0,0 +1,115 @@
+/*******************************************************************************
+ * Copyright (C) 2007 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 org.apache.taverna.activities.externaltool.manager;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.border.EmptyBorder;
+import 
org.apache.taverna.activities.externaltool.manager.InvocationGroupManager;
+import org.apache.taverna.activities.externaltool.manager.InvocationMechanism;
+
+import 
org.apache.taverna.activities.externaltool.manager.impl.InvocationGroupManagerImpl;
+
+/**
+ * UI for creating/editing dataflow input ports.
+ *
+ * @author David Withers
+ */
+public class GroupPanel extends JPanel {
+
+       private static final long serialVersionUID = 1L;
+
+       private JTextField groupNameField;
+
+       private JComboBox mechanismComboBox;
+
+       private static InvocationGroupManager manager = 
InvocationGroupManagerImpl.getInstance();
+
+       public GroupPanel(Object[] mechanisms) {
+               super(new GridBagLayout());
+
+               groupNameField = new JTextField();
+
+
+               setBorder(new EmptyBorder(10, 10, 10, 10));
+
+               GridBagConstraints constraints = new GridBagConstraints();
+
+               constraints.anchor = GridBagConstraints.WEST;
+               constraints.gridx = 0;
+               constraints.gridy = 0;
+               constraints.ipadx = 10;
+               add(new JLabel("Name:"), constraints);
+
+               constraints.gridx = 1;
+               constraints.gridwidth = 2;
+               constraints.ipadx = 0;
+               constraints.weightx = 1d;
+               constraints.fill = GridBagConstraints.HORIZONTAL;
+               add(groupNameField, constraints);
+
+               constraints.gridx = 0;
+               constraints.gridy = 1;
+               constraints.gridwidth = 1;
+               constraints.weightx = 0d;
+               constraints.fill = GridBagConstraints.NONE;
+               constraints.ipadx = 10;
+               constraints.insets = new Insets(10, 0, 0, 0);
+               add(new JLabel("Explicit location:"), constraints);
+
+               mechanismComboBox = new JComboBox(mechanisms);
+               
mechanismComboBox.setSelectedItem(manager.getDefaultMechanism());
+
+               constraints.gridx = 1;
+               constraints.gridwidth = 2;
+               constraints.ipadx = 0;
+               add(mechanismComboBox, constraints);
+       }
+
+       /**
+        * Returns the portNameField.
+        *
+        * @return the portNameField
+        */
+       public JTextField getGroupNameField() {
+               return groupNameField;
+       }
+
+       /**
+        * Returns the group name.
+        *
+        * @return the group name
+        */
+       public String getGroupName() {
+               return groupNameField.getText();
+       }
+
+       public InvocationMechanism getSelectedMechanism() {
+               return (InvocationMechanism) 
mechanismComboBox.getSelectedItem();
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/163747de/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupManagerShutdownHook.java
----------------------------------------------------------------------
diff --git 
a/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupManagerShutdownHook.java
 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupManagerShutdownHook.java
new file mode 100644
index 0000000..c3fd2e2
--- /dev/null
+++ 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupManagerShutdownHook.java
@@ -0,0 +1,34 @@
+/**
+ * 
+ */
+package org.apache.taverna.activities.externaltool.manager;
+
+import 
net.sf.taverna.t2.activities.externaltool.manager.impl.InvocationGroupManagerImpl;
+import org.apache.taverna.workbench.ShutdownSPI;
+
+/**
+ * @author alanrw
+ *
+ */
+public class InvocationGroupManagerShutdownHook implements ShutdownSPI {
+
+       /* (non-Javadoc)
+        * @see net.sf.taverna.t2.workbench.ShutdownSPI#positionHint()
+        */
+       @Override
+       public int positionHint() {
+               return 710;
+       }
+
+       /* (non-Javadoc)
+        * @see net.sf.taverna.t2.workbench.ShutdownSPI#shutdown()
+        */
+       @Override
+       public boolean shutdown() {
+               InvocationGroupManager manager = 
InvocationGroupManagerImpl.getInstance();
+               manager.saveConfiguration();
+               manager.persistInvocations();
+               return true;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/163747de/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupManagerStartupHook.java
----------------------------------------------------------------------
diff --git 
a/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupManagerStartupHook.java
 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupManagerStartupHook.java
new file mode 100644
index 0000000..5e03bf7
--- /dev/null
+++ 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupManagerStartupHook.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * Copyright (C) 2010 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 org.apache.taverna.activities.externaltool.manager;
+
+import 
org.apache.taverna.activities.externaltool.manager.impl.InvocationGroupManagerImpl;
+import org.apache.taverna.workbench.StartupSPI;
+
+/**
+ * Load previously saved workflow ids that were scheduled to be deleted before
+ * previous Taverna shutdown, and initiate deletion of them now.
+ * 
+ * @see StoreRunIdsToDeleteLaterShutdownHook
+ * @see DatabaseCleanup
+ * 
+ * @author Stian Soiland-Reyes
+ * 
+ */
+public class InvocationGroupManagerStartupHook implements StartupSPI {
+
+       public int positionHint() {
+               return 900;
+       }
+
+       public boolean startup() {
+               InvocationGroupManagerImpl.getInstance().loadInvocations();
+               return true;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/163747de/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationMechanismEditor.java
----------------------------------------------------------------------
diff --git 
a/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationMechanismEditor.java
 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationMechanismEditor.java
new file mode 100644
index 0000000..a4affaf
--- /dev/null
+++ 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationMechanismEditor.java
@@ -0,0 +1,28 @@
+/**
+ *
+ */
+package org.apache.taverna.activities.externaltool.manager;
+
+import javax.swing.JPanel;
+
+/**
+ * @author alanrw
+ *
+ */
+public abstract class InvocationMechanismEditor<T extends InvocationMechanism> 
extends JPanel {
+
+       public abstract String getName();
+
+       public abstract boolean canShow(Class<?> c);
+
+       public abstract void show(T invocationMechanism);
+
+       public abstract T updateInvocationMechanism();
+
+       public abstract InvocationMechanism createMechanism(String 
mechanismName);
+
+       public boolean isSingleton() {
+               return false;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/163747de/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/MechanismPanel.java
----------------------------------------------------------------------
diff --git 
a/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/MechanismPanel.java
 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/MechanismPanel.java
new file mode 100644
index 0000000..7f85c68
--- /dev/null
+++ 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/MechanismPanel.java
@@ -0,0 +1,121 @@
+/*******************************************************************************
+ * Copyright (C) 2007 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 org.apache.taverna.activities.externaltool.manager;
+
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.util.List;
+
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.border.EmptyBorder;
+
+/**
+ * UI for creating/editing dataflow input ports.
+ *
+ * @author David Withers
+ */
+public class MechanismPanel extends JPanel {
+
+       private static final long serialVersionUID = 1L;
+
+       private JTextField mechanismNameField;
+
+       private JComboBox mechanismTypeSelector;
+
+       public MechanismPanel(List<InvocationMechanismEditor<?>> 
invocationMechanismEditors) {
+               super(new GridBagLayout());
+
+               mechanismNameField = new JTextField();
+
+
+               setBorder(new EmptyBorder(10, 10, 10, 10));
+
+               GridBagConstraints constraints = new GridBagConstraints();
+
+               constraints.anchor = GridBagConstraints.WEST;
+               constraints.gridx = 0;
+               constraints.gridy = 0;
+               constraints.ipadx = 10;
+               add(new JLabel("Name:"), constraints);
+
+               constraints.gridx = 1;
+               constraints.gridwidth = 2;
+               constraints.ipadx = 0;
+               constraints.weightx = 1d;
+               constraints.fill = GridBagConstraints.HORIZONTAL;
+               add(mechanismNameField, constraints);
+
+               constraints.gridx = 0;
+               constraints.gridy = 1;
+               constraints.gridwidth = 1;
+               constraints.weightx = 0d;
+               constraints.fill = GridBagConstraints.NONE;
+               constraints.ipadx = 10;
+               constraints.insets = new Insets(10, 0, 0, 0);
+               add(new JLabel("Type:"), constraints);
+
+               mechanismTypeSelector = new JComboBox();
+               for (InvocationMechanismEditor<?> ime : 
invocationMechanismEditors) {
+                       if (!ime.isSingleton()) {
+                               mechanismTypeSelector.addItem(ime.getName());
+                       }
+               }
+               constraints.gridx = 1;
+               constraints.gridwidth = 2;
+               constraints.ipadx = 0;
+               add(mechanismTypeSelector, constraints);
+
+
+       }
+
+       /**
+        * Returns the portNameField.
+        *
+        * @return the portNameField
+        */
+       public JTextField getMechanismNameField() {
+               return mechanismNameField;
+       }
+
+       /**
+        * Returns the port name.
+        *
+        * @return the port name
+        */
+       public String getMechanismName() {
+               return mechanismNameField.getText();
+       }
+
+       public String getMechanismTypeName() {
+               return (String) mechanismTypeSelector.getSelectedItem();
+       }
+
+       public Component getMechanismTypeSelector() {
+               return mechanismTypeSelector;
+       }
+
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/163747de/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/ToolInvocationConfigurationPanel.java
----------------------------------------------------------------------
diff --git 
a/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/ToolInvocationConfigurationPanel.java
 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/ToolInvocationConfigurationPanel.java
new file mode 100644
index 0000000..cabd832
--- /dev/null
+++ 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/ToolInvocationConfigurationPanel.java
@@ -0,0 +1,383 @@
+/**
+ *
+ */
+package org.apache.taverna.activities.externaltool.manager;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+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.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.swing.AbstractAction;
+import javax.swing.DefaultListCellRenderer;
+import javax.swing.DefaultListModel;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.ListSelectionModel;
+import javax.swing.SwingUtilities;
+import javax.swing.border.EmptyBorder;
+import org.apache.taverna.activities.externaltool.manager.InvocationGroup;
+import 
org.apache.taverna.activities.externaltool.manager.InvocationManagerEvent;
+import org.apache.taverna.activities.externaltool.manager.InvocationMechanism;
+import org.apache.taverna.activities.externaltool.manager.MechanismCreator;
+
+import 
org.apache.taverna.activities.externaltool.manager.impl.InvocationGroupManagerImpl;
+import org.apache.taverna.lang.observer.Observable;
+import org.apache.taverna.lang.observer.Observer;
+import org.apache.taverna.lang.ui.DeselectingButton;
+import org.apache.taverna.lang.ui.ValidatingUserInputDialog;
+import org.apache.taverna.workbench.helper.Helper;
+
+/**
+ * @author alanrw
+ *
+ */
+public class ToolInvocationConfigurationPanel extends JPanel implements
+               Observer<InvocationManagerEvent> {
+
+       public static final String HEADER_TEXT = "A tool can be set to run at 
an explicit location (e.g. on a specificic machine or one of a set of 
machines). Alternatively, it can be set to run at a symbolic location, which 
means the tool will then be run at the explicit location pointed to by the 
symbolic location.";
+
+       private static InvocationGroupManagerImpl manager = 
InvocationGroupManagerImpl.getInstance();
+
+       private final List<InvocationMechanismEditor<?>> 
invocationMechanismEditors;
+
+       private JTextArea headerText;
+
+       private static String EXPLICIT_LOCATIONS = "explicit locations";
+       private static String SYMBOLIC_LOCATIONS = "symbolic locations";
+
+       private List<MechanismCreator> mechanismCreators;
+
+       JList locationList = new JList();
+
+       DefaultListModel groupListModel = new DefaultListModel();
+       DefaultListModel mechanismListModel = new DefaultListModel();
+       JComboBox locationTypeCombo = new JComboBox(new String[] { 
EXPLICIT_LOCATIONS,
+                       SYMBOLIC_LOCATIONS });
+
+       public ToolInvocationConfigurationPanel(List<MechanismCreator> 
mechanismCreators,
+                       List<InvocationMechanismEditor<?>> 
invocationMechanismEditors) {
+               super();
+               this.mechanismCreators = mechanismCreators;
+               this.invocationMechanismEditors = invocationMechanismEditors;
+               manager.addObserver(this);
+
+               this.setLayout(new GridBagLayout());
+               GridBagConstraints gbc = new GridBagConstraints();
+
+               headerText = new JTextArea(HEADER_TEXT);
+               headerText.setLineWrap(true);
+               headerText.setWrapStyleWord(true);
+               headerText.setEditable(false);
+               headerText.setFocusable(false);
+               headerText.setBorder(new EmptyBorder(10, 10, 10, 10));
+
+               gbc.anchor = GridBagConstraints.WEST;
+               gbc.insets = new Insets(0, 0, 10, 0);
+               gbc.gridx = 0;
+               gbc.gridy = 0;
+               gbc.gridwidth = 1;
+               gbc.weightx = 1.0;
+               gbc.weighty = 0.0;
+               gbc.fill = GridBagConstraints.HORIZONTAL;
+               add(headerText, gbc);
+
+               JPanel locationPanel = new JPanel(new BorderLayout());
+               JPanel subPanel = new JPanel(new FlowLayout());
+               JLabel modify = new JLabel("Modify:");
+
+               locationTypeCombo.setSelectedItem(EXPLICIT_LOCATIONS);
+               locationTypeCombo.addActionListener(new ActionListener() {
+
+                       @Override
+                       public void actionPerformed(ActionEvent e) {
+                               switchList();
+                       }
+               });
+               subPanel.add(modify);
+               subPanel.add(locationTypeCombo);
+
+               populateLists();
+               switchList();
+               
locationList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+               locationList.setCellRenderer(new DefaultListCellRenderer() {
+                       public Component getListCellRendererComponent(JList 
list, Object value, int index,
+                                       boolean isSelected, boolean 
cellHasFocus) {
+                               Object toShow = value;
+                               if (value instanceof InvocationGroup) {
+                                       InvocationGroup invocationGroup = 
(InvocationGroup) value;
+                                       toShow = invocationGroup.getName() + "  
-->  "
+                                                       + 
invocationGroup.getMechanismName();
+                               }
+                               return super.getListCellRendererComponent(list, 
toShow, index, isSelected,
+                                               cellHasFocus);
+                       }
+               });
+               locationPanel.add(new JScrollPane(locationList), 
BorderLayout.CENTER);
+               locationPanel.add(subPanel, BorderLayout.NORTH);
+
+               JPanel buttonPanel = new JPanel(new FlowLayout());
+               JButton helpButton = new DeselectingButton("Help", new 
AbstractAction() {
+
+                       public void actionPerformed(ActionEvent e) {
+                               
Helper.showHelp(ToolInvocationConfigurationPanel.this);
+                       }
+               });
+
+               buttonPanel.add(helpButton);
+
+               buttonPanel.add(addLocationButton());
+               buttonPanel.add(removeLocationButton());
+               buttonPanel.add(editLocationButton());
+               locationPanel.add(buttonPanel, BorderLayout.SOUTH);
+
+               gbc.gridy++;
+               gbc.weighty = 1;
+
+               gbc.fill = GridBagConstraints.BOTH;
+               gbc.anchor = GridBagConstraints.SOUTH;
+               gbc.insets = new Insets(10, 0, 0, 0);
+               this.add(locationPanel, gbc);
+       }
+
+       private void switchList() {
+               if (isShowingGroups()) {
+                       locationList.setModel(groupListModel);
+               } else {
+                       locationList.setModel(mechanismListModel);
+               }
+       }
+
+       private void populateLists() {
+               poopulateGroupList();
+               populateMechanismList();
+       }
+
+       private void populateMechanismList() {
+               Object currentSelection = locationList.getSelectedValue();
+               ArrayList<InvocationMechanism> mechanisms = new 
ArrayList<InvocationMechanism>();
+               mechanisms.addAll(manager.getMechanisms());
+               Collections.sort(mechanisms, new 
Comparator<InvocationMechanism>() {
+
+                       @Override
+                       public int compare(InvocationMechanism o1, 
InvocationMechanism o2) {
+                               return o1.getName().compareTo(o2.getName());
+                       }
+               });
+               mechanismListModel.clear();
+               for (InvocationMechanism m : mechanisms) {
+                       mechanismListModel.addElement(m);
+               }
+               if ((currentSelection != null) && !isShowingGroups()) {
+                       locationList.setSelectedValue(currentSelection, true);
+               }
+       }
+
+       private void poopulateGroupList() {
+               Object currentSelection = locationList.getSelectedValue();
+               ArrayList<InvocationGroup> groups = new 
ArrayList<InvocationGroup>();
+               groups.addAll(manager.getInvocationGroups());
+               Collections.sort(groups, new Comparator<InvocationGroup>() {
+
+                       @Override
+                       public int compare(InvocationGroup o1, InvocationGroup 
o2) {
+                               return o1.getName().compareTo(o2.getName());
+                       }
+               });
+               groupListModel.clear();
+               for (InvocationGroup g : groups) {
+                       groupListModel.addElement(g);
+               }
+               if ((currentSelection != null) && isShowingGroups()) {
+                       locationList.setSelectedValue(currentSelection, true);
+               }
+       }
+
+       private boolean isShowingGroups() {
+               return 
(locationTypeCombo.getSelectedItem().equals(SYMBOLIC_LOCATIONS));
+       }
+
+       private JButton addLocationButton() {
+               final JButton result = new DeselectingButton("Add", new 
AbstractAction() {
+
+                       @Override
+                       public void actionPerformed(ActionEvent e) {
+                               if (isShowingGroups()) {
+                                       Set<String> usedGroupNames = new 
HashSet<String>();
+                                       for (InvocationGroup g : 
manager.getInvocationGroups()) {
+                                               usedGroupNames.add(g.getName());
+                                       }
+
+                                       GroupPanel inputPanel = new 
GroupPanel(mechanismListModel.toArray());
+
+                                       ValidatingUserInputDialog vuid = new 
ValidatingUserInputDialog(
+                                                       "Add symbolic 
location", inputPanel);
+                                       
vuid.addTextComponentValidation(inputPanel.getGroupNameField(),
+                                                       "Set the symbolic 
location name.", usedGroupNames,
+                                                       "Duplicate symbolic 
location name.", "[\\p{L}\\p{Digit}_.]+",
+                                                       "Invalid symbolic 
location name.");
+                                       vuid.setSize(new Dimension(400, 250));
+
+                                       if 
(vuid.show(ToolInvocationConfigurationPanel.this)) {
+                                               String groupName = 
inputPanel.getGroupName();
+                                               InvocationGroup newGroup = new 
InvocationGroup(mechanismCreators);
+                                               newGroup.setName(groupName);
+                                               
newGroup.setMechanism(inputPanel.getSelectedMechanism());
+                                               
manager.addInvocationGroup(newGroup);
+                                               
locationList.setSelectedValue(newGroup, true);
+                                       }
+                               } else {
+                                       Set<String> usedNames = new 
HashSet<String>();
+                                       for (InvocationMechanism m : 
manager.getMechanisms()) {
+                                               usedNames.add(m.getName());
+                                       }
+
+                                       MechanismPanel inputPanel = new 
MechanismPanel(invocationMechanismEditors);
+
+                                       ValidatingUserInputDialog vuid = new 
ValidatingUserInputDialog(
+                                                       "Add explicit 
location", inputPanel);
+                                       
vuid.addTextComponentValidation(inputPanel.getMechanismNameField(),
+                                                       "Set the explicit 
location name.", usedNames,
+                                                       "Duplicate explicit 
location name.", "[\\p{L}\\p{Digit}_.]+",
+                                                       "Invalid explicit 
location name.");
+                                       
vuid.addMessageComponent(inputPanel.getMechanismTypeSelector(),
+                                                       "Set the location name 
and type.");
+                                       vuid.setSize(new Dimension(400, 250));
+
+                                       if 
(vuid.show(ToolInvocationConfigurationPanel.this)) {
+                                               String mechanismName = 
inputPanel.getMechanismName();
+                                               String mechanismTypeName = 
inputPanel.getMechanismTypeName();
+                                               InvocationMechanismEditor ime = 
findEditor(mechanismTypeName);
+                                               InvocationMechanism 
newMechanism = ime.createMechanism(mechanismName);
+                                               
manager.addMechanism(newMechanism);
+                                               ime.show(newMechanism);
+                                               ime.setPreferredSize(new 
Dimension(550, 500));
+                                               int answer = 
JOptionPane.showConfirmDialog(
+                                                               
ToolInvocationConfigurationPanel.this, ime,
+                                                               "New explicit 
location", JOptionPane.OK_CANCEL_OPTION,
+                                                               
JOptionPane.PLAIN_MESSAGE, null);
+                                               if (answer == 
JOptionPane.OK_OPTION) {
+                                                       
ime.updateInvocationMechanism();
+                                                       
InvocationGroupManagerImpl.getInstance().mechanismChanged(newMechanism);
+                                               }
+                                               
locationList.setSelectedValue(newMechanism, true);
+                                       }
+                               }
+                       }
+               });
+               return result;
+       }
+
+       private JButton removeLocationButton() {
+               JButton result = new DeselectingButton("Remove", new 
AbstractAction() {
+
+                       @Override
+                       public void actionPerformed(ActionEvent e) {
+                               if (isShowingGroups()) {
+                                       InvocationGroup toRemove = 
(InvocationGroup) locationList.getSelectedValue();
+                                       if ((toRemove != null) && 
!toRemove.equals(manager.getDefaultGroup())) {
+                                               
manager.removeInvocationGroup(toRemove);
+                                       }
+                                       
locationList.setSelectedValue(manager.getDefaultGroup(), true);
+                               } else {
+                                       InvocationMechanism toRemove = 
(InvocationMechanism) locationList
+                                                       .getSelectedValue();
+                                       if ((toRemove != null) && 
!toRemove.equals(manager.getDefaultMechanism())) {
+                                               
manager.removeMechanism(toRemove);
+                                               
locationList.setSelectedValue(manager.getDefaultMechanism(), true);
+                                       }
+                               }
+                       }
+               });
+               return result;
+       }
+
+       private JButton editLocationButton() {
+               final JButton result = new DeselectingButton("Edit", new 
AbstractAction() {
+
+                       @Override
+                       public void actionPerformed(ActionEvent e) {
+                               if (isShowingGroups()) {
+                                       InvocationGroup toEdit = 
(InvocationGroup) locationList.getSelectedValue();
+                                       if (toEdit != null) {
+                                               InvocationMechanism 
chosenMechanism = (InvocationMechanism) JOptionPane
+                                                               
.showInputDialog(ToolInvocationConfigurationPanel.this,
+                                                                               
"Select an explicit location", "Edit symbolic location",
+                                                                               
JOptionPane.PLAIN_MESSAGE, null,
+                                                                               
mechanismListModel.toArray(), toEdit.getMechanism());
+                                               if (chosenMechanism != null) {
+                                                       
toEdit.setMechanism(chosenMechanism);
+                                                       
manager.groupChanged(toEdit);
+                                               }
+                                       }
+                               } else {
+                                       InvocationMechanism toEdit = 
(InvocationMechanism) locationList
+                                                       .getSelectedValue();
+                                       if (toEdit != null) {
+                                               InvocationMechanismEditor ime = 
findEditor(toEdit.getClass());
+                                               ime.show(toEdit);
+                                               ime.setPreferredSize(new 
Dimension(550, 500));
+                                               int answer = 
JOptionPane.showConfirmDialog(
+                                                               
ToolInvocationConfigurationPanel.this, ime,
+                                                               "Edit explicit 
location", JOptionPane.OK_CANCEL_OPTION,
+                                                               
JOptionPane.PLAIN_MESSAGE, null);
+                                               if (answer == 
JOptionPane.OK_OPTION) {
+                                                       
ime.updateInvocationMechanism();
+                                                       
InvocationGroupManagerImpl.getInstance().mechanismChanged(toEdit);
+                                               }
+                                       }
+                               }
+                       }
+               });
+               return result;
+       }
+
+       protected InvocationMechanismEditor findEditor(String name) {
+               for (InvocationMechanismEditor ime : 
invocationMechanismEditors) {
+                       if (ime.getName().equalsIgnoreCase(name)) {
+                               return ime;
+                       }
+               }
+               return null;
+       }
+
+       protected InvocationMechanismEditor findEditor(Class c) {
+               for (InvocationMechanismEditor ime : 
invocationMechanismEditors) {
+                       if (ime.canShow(c)) {
+                               return ime;
+                       }
+               }
+               return null;
+       }
+
+       @Override
+       public void notify(Observable<InvocationManagerEvent> arg0, 
InvocationManagerEvent arg1)
+                       throws Exception {
+               if (SwingUtilities.isEventDispatchThread()) {
+                       populateLists();
+               } else {
+                       SwingUtilities.invokeLater(new Runnable() {
+                               public void run() {
+                                       populateLists();
+                               }
+                       });
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/163747de/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/ToolInvocationConfigurationUIFactory.java
----------------------------------------------------------------------
diff --git 
a/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/ToolInvocationConfigurationUIFactory.java
 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/ToolInvocationConfigurationUIFactory.java
new file mode 100644
index 0000000..3002a35
--- /dev/null
+++ 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/ToolInvocationConfigurationUIFactory.java
@@ -0,0 +1,55 @@
+/**
+ *
+ */
+package org.apache.taverna.activities.externaltool.manager;
+
+import java.util.List;
+
+import javax.swing.JPanel;
+
+import uk.org.taverna.configuration.Configurable;
+import uk.org.taverna.configuration.ConfigurationUIFactory;
+
+import 
org.apache.taverna.activities.externaltool.configuration.ToolInvocationConfiguration;
+import org.apache.taverna.activities.externaltool.manager.MechanismCreator;
+
+/**
+ * @author alanrw
+ *
+ */
+public class ToolInvocationConfigurationUIFactory implements 
ConfigurationUIFactory {
+
+       private List<MechanismCreator> mechanismCreators;
+       private List<InvocationMechanismEditor<?>> invocationMechanismEditors;
+
+       private ToolInvocationConfigurationPanel configPanel;
+
+       @Override
+       public boolean canHandle(String uuid) {
+               return uuid.equals(getConfigurable().getUUID());
+       }
+
+       @Override
+       public Configurable getConfigurable() {
+               return ToolInvocationConfiguration.getInstance();
+       }
+
+       @Override
+       public JPanel getConfigurationPanel() {
+               if (configPanel == null) {
+                       configPanel = new 
ToolInvocationConfigurationPanel(mechanismCreators,
+                                       invocationMechanismEditors);
+               }
+               return configPanel;
+       }
+
+       public void setMechanismCreators(List<MechanismCreator> 
mechanismCreators) {
+               this.mechanismCreators = mechanismCreators;
+       }
+
+       public void setInvocationMechanismEditors(
+                       List<InvocationMechanismEditor<?>> 
invocationMechanismEditors) {
+               this.invocationMechanismEditors = invocationMechanismEditors;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/163747de/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/local/LocalInvocationMechanismEditor.java
----------------------------------------------------------------------
diff --git 
a/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/local/LocalInvocationMechanismEditor.java
 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/local/LocalInvocationMechanismEditor.java
new file mode 100644
index 0000000..70918f5
--- /dev/null
+++ 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/local/LocalInvocationMechanismEditor.java
@@ -0,0 +1,122 @@
+/**
+ * 
+ */
+package org.apache.taverna.activities.externaltool.manager.local;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+import 
org.apache.taverna.activities.externaltool.local.ExternalToolLocalInvocationMechanism;
+import org.apache.taverna.activities.externaltool.manager.InvocationMechanism;
+import 
org.apache.taverna.activities.externaltool.manager.InvocationMechanismEditor;
+
+/**
+ * @author alanrw
+ *
+ */
+public final class LocalInvocationMechanismEditor extends
+               InvocationMechanismEditor<ExternalToolLocalInvocationMechanism> 
{
+
+       private ExternalToolLocalInvocationMechanism invocationMechanism;
+       
+       private JTextField directoryField = new JTextField(30);
+       
+       private JTextField shellPrefixField = new JTextField(30);
+       
+       private JTextField linkCommandField = new JTextField(30);
+       
+       private JCheckBox retrieveDataField = new JCheckBox();
+       
+
+       @Override
+       public boolean canShow(Class<?> c) {
+               return 
ExternalToolLocalInvocationMechanism.class.isAssignableFrom(c);
+       }
+
+       @Override
+       public String getName() {
+               return ("Local");
+       }
+
+       @Override
+       public void show(ExternalToolLocalInvocationMechanism 
invocationMechanism) {
+               this.invocationMechanism = invocationMechanism;
+               this.removeAll();
+               final JPanel innerPanel = new JPanel(new GridBagLayout());
+               final GridBagConstraints inputConstraint = new 
GridBagConstraints();
+//             inputConstraint.insets = new Insets(5,5,5,5);
+               inputConstraint.anchor = GridBagConstraints.FIRST_LINE_START;
+               inputConstraint.gridx = 0;
+               inputConstraint.gridy = 0;
+               inputConstraint.weightx = 0.1;
+               inputConstraint.fill = GridBagConstraints.BOTH;
+               innerPanel.add(new JLabel("Working directory: "), 
inputConstraint);
+               inputConstraint.gridx++;
+               directoryField.setText(invocationMechanism.getDirectory());
+               innerPanel.add(directoryField, inputConstraint);
+               inputConstraint.gridx = 0;
+               inputConstraint.gridy++;
+               innerPanel.add(new JLabel("Shell: "), inputConstraint);
+               inputConstraint.gridx++;
+               shellPrefixField.setText(invocationMechanism.getShellPrefix());
+               innerPanel.add(shellPrefixField, inputConstraint);
+               
+               inputConstraint.gridx = 0;
+               inputConstraint.gridy++;
+               innerPanel.add(new JLabel("Link command: "), inputConstraint);
+               inputConstraint.gridx++;
+               linkCommandField.setText(invocationMechanism.getLinkCommand());
+               innerPanel.add(linkCommandField, inputConstraint);
+               
+               inputConstraint.gridx = 0;
+               inputConstraint.gridy++;
+               innerPanel.add(new JLabel("Fetch data: "), inputConstraint);
+               inputConstraint.gridx++;
+               
retrieveDataField.setSelected(invocationMechanism.isRetrieveData());
+               innerPanel.add(retrieveDataField, inputConstraint);
+               
+               this.add(innerPanel);
+       }
+
+       @Override
+       public ExternalToolLocalInvocationMechanism updateInvocationMechanism() 
{
+               if ((directoryField.getText() == null) || 
(directoryField.getText().length() == 0)) {
+                       invocationMechanism.setDirectory(null);
+               } else {
+                       
invocationMechanism.setDirectory(directoryField.getText());
+               }
+               if ((shellPrefixField.getText() == null) || 
(shellPrefixField.getText().length() == 0)) {
+                       invocationMechanism.setShellPrefix(null);
+               } else {
+                       
invocationMechanism.setShellPrefix(shellPrefixField.getText());
+               }
+               if ((shellPrefixField.getText() == null) || 
(shellPrefixField.getText().length() == 0)) {
+                       invocationMechanism.setShellPrefix(null);
+               } else {
+                       
invocationMechanism.setShellPrefix(shellPrefixField.getText());
+               }
+               if ((linkCommandField.getText() == null) || 
(linkCommandField.getText().length() == 0)) {
+                       invocationMechanism.setLinkCommand(null);
+               } else {
+                       
invocationMechanism.setLinkCommand(linkCommandField.getText());
+               }
+               
invocationMechanism.setRetrieveData(retrieveDataField.isSelected());
+               return invocationMechanism;
+       }
+
+       @Override
+       public InvocationMechanism createMechanism(String mechanismName) {
+               ExternalToolLocalInvocationMechanism result = new 
ExternalToolLocalInvocationMechanism();
+               result.setName(mechanismName);
+               return(result);
+       }
+
+       public boolean isSingleton() {
+               return true;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/163747de/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/ssh/ExternalToolSshNodeViewer.java
----------------------------------------------------------------------
diff --git 
a/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/ssh/ExternalToolSshNodeViewer.java
 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/ssh/ExternalToolSshNodeViewer.java
new file mode 100644
index 0000000..676d16d
--- /dev/null
+++ 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/ssh/ExternalToolSshNodeViewer.java
@@ -0,0 +1,110 @@
+/**
+ * 
+ */
+package org.apache.taverna.activities.externaltool.manager.ssh;
+
+import javax.swing.JCheckBox;
+import javax.swing.JTextField;
+
+import org.apache.taverna.activities.externaltool.manager.InvocationMechanism;
+
+import de.uni_luebeck.inb.knowarc.usecases.invocation.ssh.SshNode;
+
+
+
+/**
+ * @author alanrw
+ *
+ */
+public class ExternalToolSshNodeViewer {
+       
+       private JTextField hostnameField;
+       private JTextField portField;
+       private JTextField directoryField;
+       private JTextField linkCommandField;
+       private JTextField copyCommandField;
+       private JCheckBox retrieveDataField;
+
+       public ExternalToolSshNodeViewer(SshNode node) {
+               this();
+               hostnameField.setText(node.getHost());
+               portField.setText(Integer.toString(node.getPort()));
+               if (node.getDirectory() != null) {
+                       directoryField.setText(node.getDirectory());
+               } else {
+                       directoryField.setText("");
+               }
+               if (node.getLinkCommand() != null) {
+                       linkCommandField.setText(node.getLinkCommand());
+               } else {
+                       linkCommandField.setText("");
+               }
+               if (node.getCopyCommand() != null) {
+                       copyCommandField.setText(node.getCopyCommand());
+               } else {
+                       copyCommandField.setText("");
+               }
+               retrieveDataField.setSelected(node.isRetrieveData());
+       }
+
+       public ExternalToolSshNodeViewer() {
+               hostnameField = new JTextField(30);
+               hostnameField.setText(SshNode.DEFAULT_HOST);
+               portField = new JTextField(3);
+               portField.setText("" + SshNode.DEFAULT_PORT);
+               directoryField = new JTextField(30);
+               directoryField.setText(SshNode.DEFAULT_DIRECTORY);
+               linkCommandField = new JTextField(30);
+               linkCommandField.setText(InvocationMechanism.UNIX_LINK);
+               copyCommandField = new JTextField(30);
+               copyCommandField.setText(InvocationMechanism.UNIX_COPY);
+               retrieveDataField = new JCheckBox();
+       }
+
+       public JTextField getHostnameField() {
+               return hostnameField;
+       }
+
+       public JTextField getPortField() {
+               return portField;
+       }
+       
+       public JTextField getDirectoryField() {
+               return directoryField;
+       }
+
+       public JTextField getLinkCommandField() {
+               return linkCommandField;
+       }
+
+       public JTextField getCopyCommandField() {
+               return copyCommandField;
+       }
+
+       public String getHostname() {
+               return hostnameField.getText();
+       }
+
+       public int getPort() {
+               return Integer.parseInt(portField.getText());
+       }
+       
+       public String getDirectory() {
+               return directoryField.getText();
+       }
+       
+       public String getLinkCommand() {
+               return linkCommandField.getText();
+       }
+       
+       public String getCopyCommand() {
+               return copyCommandField.getText();
+       }
+
+       /**
+        * @return the retrieveDataField
+        */
+       public JCheckBox getRetrieveDataField() {
+               return retrieveDataField;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/163747de/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/ssh/SshInvocationMechanismEditor.java
----------------------------------------------------------------------
diff --git 
a/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/ssh/SshInvocationMechanismEditor.java
 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/ssh/SshInvocationMechanismEditor.java
new file mode 100644
index 0000000..1fd3c2b
--- /dev/null
+++ 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/manager/ssh/SshInvocationMechanismEditor.java
@@ -0,0 +1,234 @@
+/**
+ * 
+ */
+package org.apache.taverna.activities.externaltool.manager.ssh;
+
+import java.awt.Color;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.AbstractAction;
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextField;
+import javax.swing.border.CompoundBorder;
+
+import net.sf.taverna.t2.activities.externaltool.manager.InvocationMechanism;
+import 
org.apache.taverna.activities.externaltool.manager.InvocationMechanismEditor;
+import 
net.sf.taverna.t2.activities.externaltool.ssh.ExternalToolSshInvocationMechanism;
+import net.sf.taverna.t2.lang.ui.DeselectingButton;
+import de.uni_luebeck.inb.knowarc.usecases.invocation.ssh.SshNode;
+import de.uni_luebeck.inb.knowarc.usecases.invocation.ssh.SshNodeFactory;
+
+/**
+ * @author alanrw
+ *
+ */
+public final class SshInvocationMechanismEditor extends
+               InvocationMechanismEditor<ExternalToolSshInvocationMechanism> {
+       
+       private ArrayList<ExternalToolSshNodeViewer> nodeViewers = new 
ArrayList<ExternalToolSshNodeViewer>();
+       private int inputGridy = 0;
+       
+       private ExternalToolSshInvocationMechanism mechanism = null;
+       
+       private static Insets insets = new Insets(1,5,1,5);
+       
+       private static CompoundBorder border = 
BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(5,5,5,5), 
BorderFactory.createLineBorder(Color.BLACK, 1));
+
+       @Override
+       public boolean canShow(Class<?> c) {
+               return 
ExternalToolSshInvocationMechanism.class.isAssignableFrom(c);
+       }
+
+       @Override
+       public void show(ExternalToolSshInvocationMechanism 
invocationMechanism) {
+               mechanism = invocationMechanism;
+               this.removeAll();
+               inputGridy = 1;
+               final JPanel innerPanel = new JPanel(new GridBagLayout());
+
+               final GridBagConstraints inputConstraint = new 
GridBagConstraints();
+               inputConstraint.anchor = GridBagConstraints.FIRST_LINE_START;
+               inputConstraint.gridx = 0;
+               inputConstraint.gridy = 0;
+               inputConstraint.weightx = 0.1;
+               inputConstraint.fill = GridBagConstraints.BOTH;
+
+               inputConstraint.gridx = 0;
+                       nodeViewers.clear();
+                       for (SshNode node : invocationMechanism.getNodes()) {
+                               ExternalToolSshNodeViewer nodeViewer = new 
ExternalToolSshNodeViewer(node);
+                               addNodeViewer(this, innerPanel, nodeViewer);
+                       }
+
+               this.setLayout(new GridBagLayout());
+               GridBagConstraints outerPanelConstraint = new 
GridBagConstraints();
+               outerPanelConstraint.gridx = 0;
+               outerPanelConstraint.gridy = 0;
+               outerPanelConstraint.weightx = 0.1;
+               outerPanelConstraint.weighty = 0.1;
+               outerPanelConstraint.fill = GridBagConstraints.BOTH;
+               this.add(new JScrollPane(innerPanel),
+                               outerPanelConstraint);
+               outerPanelConstraint.weighty = 0;
+               final JButton addHostButton = new DeselectingButton("Add host",
+                               new AbstractAction() {
+                       public void actionPerformed(ActionEvent e) {
+
+                               ExternalToolSshNodeViewer newViewer = new 
ExternalToolSshNodeViewer();
+
+                                       
addNodeViewer(SshInvocationMechanismEditor.this, innerPanel, newViewer);
+                                       innerPanel.revalidate();
+                                       innerPanel.repaint();
+                       }
+
+               });
+               JPanel buttonPanel = new JPanel();
+               buttonPanel.setLayout(new GridBagLayout());
+
+               JPanel filler = new JPanel();
+               outerPanelConstraint.weightx = 0.1;
+               outerPanelConstraint.weighty = 0;
+               outerPanelConstraint.gridx = 0;
+               outerPanelConstraint.gridy = 0;
+
+               buttonPanel.add(filler, outerPanelConstraint);
+
+               outerPanelConstraint.weightx = 0;
+               outerPanelConstraint.weighty = 0;
+               outerPanelConstraint.gridx = 1;
+               outerPanelConstraint.gridy = 0;
+
+               buttonPanel.add(addHostButton, outerPanelConstraint);
+
+               outerPanelConstraint.weightx = 0;
+               outerPanelConstraint.weighty = 0;
+               outerPanelConstraint.gridx = 0;
+               outerPanelConstraint.gridy = 1;
+               outerPanelConstraint.fill = GridBagConstraints.BOTH;
+               this.add(buttonPanel, outerPanelConstraint);
+       }
+
+       protected void addNodeViewer(final JPanel result, final JPanel 
innerPanel,
+                       ExternalToolSshNodeViewer viewer) {
+               final JPanel subPanel = new JPanel();
+               subPanel.setLayout(new GridBagLayout());
+               subPanel.setBorder(border);
+               final GridBagConstraints inputConstraint = new 
GridBagConstraints();
+               inputConstraint.insets = insets;
+               inputConstraint.anchor = GridBagConstraints.FIRST_LINE_START;
+               inputConstraint.weightx = 0.1;
+               inputConstraint.fill = GridBagConstraints.BOTH;
+
+               inputConstraint.gridy = 0 ;
+               inputConstraint.gridx = 0;
+               
+               subPanel.add(new JLabel("Host: "), inputConstraint);
+               final JTextField hostnameField = viewer.getHostnameField();
+               inputConstraint.gridx++;
+               subPanel.add(hostnameField, inputConstraint);
+
+               inputConstraint.gridy++ ;
+               inputConstraint.gridx = 0;
+               subPanel.add(new JLabel("Port: "), inputConstraint);
+               final JTextField portField = viewer.getPortField();
+               inputConstraint.gridx++;
+               subPanel.add(portField ,inputConstraint);
+               
+               inputConstraint.gridy++ ;
+               inputConstraint.gridx = 0;
+               subPanel.add(new JLabel("Working directory: "), 
inputConstraint);
+               final JTextField directoryField = viewer.getDirectoryField();
+               inputConstraint.gridx++;
+               subPanel.add(directoryField ,inputConstraint);
+               
+               inputConstraint.gridy++ ;
+               inputConstraint.gridx = 0;
+               subPanel.add(new JLabel("Link command: "), inputConstraint);
+               final JTextField linkCommandField = 
viewer.getLinkCommandField();
+               inputConstraint.gridx++;
+               subPanel.add(linkCommandField ,inputConstraint);
+
+               inputConstraint.gridy++ ;
+               inputConstraint.gridx = 0;
+               subPanel.add(new JLabel("Copy command: "), inputConstraint);
+               final JTextField copyCommandField = 
viewer.getCopyCommandField();
+               inputConstraint.gridx++;
+               subPanel.add(copyCommandField ,inputConstraint);
+
+               inputConstraint.gridy++ ;
+               inputConstraint.gridx = 0;
+               subPanel.add(new JLabel("Fetch data: "), inputConstraint);
+               inputConstraint.gridx++;
+               final JCheckBox retrieveDataField = 
viewer.getRetrieveDataField();
+               subPanel.add(retrieveDataField ,inputConstraint);
+
+               inputConstraint.gridy++ ;
+               inputConstraint.gridx = 1;
+               inputConstraint.fill = GridBagConstraints.NONE;
+               inputConstraint.anchor = GridBagConstraints.EAST;
+               final ExternalToolSshNodeViewer v = viewer;
+               final JButton removeButton = new DeselectingButton("Remove",
+                               new AbstractAction() {
+
+                       public void actionPerformed(ActionEvent e) {
+                               synchronized(nodeViewers) {
+                                       nodeViewers.remove(v);
+                               }
+                               innerPanel.remove(subPanel);
+                               innerPanel.revalidate();
+                               innerPanel.repaint();
+                               result.revalidate();
+                               result.repaint();
+                       }
+
+               });
+               subPanel.add(removeButton, inputConstraint);
+               
+               inputConstraint.gridy = ++inputGridy;
+               innerPanel.add(subPanel, inputConstraint);
+
+               nodeViewers.add(viewer);
+               inputGridy++;           
+       }
+
+       private List<SshNode> getNodeList() {
+               List<SshNode> result = new ArrayList<SshNode>();
+               for (ExternalToolSshNodeViewer viewer : nodeViewers) {
+                       SshNode node = 
SshNodeFactory.getInstance().getSshNode(viewer.getHostname(), viewer.getPort(), 
viewer.getDirectory());
+                       node.setLinkCommand(viewer.getLinkCommand());
+                       node.setCopyCommand(viewer.getCopyCommand());
+                       
node.setRetrieveData(viewer.getRetrieveDataField().isSelected());
+                       result.add(node);
+               }
+               return result;
+       }
+
+       @Override
+       public ExternalToolSshInvocationMechanism updateInvocationMechanism() {
+               mechanism.setNodes(getNodeList());
+               return mechanism;
+       }
+
+       @Override
+       public InvocationMechanism createMechanism(String mechanismName) {
+               ExternalToolSshInvocationMechanism result = new 
ExternalToolSshInvocationMechanism();
+               result.setName(mechanismName);
+               return result;
+       }
+
+       @Override
+       public String getName() {
+               return ("SSH");
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/163747de/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/menu/AddExternalToolContextualMenuAction.java
----------------------------------------------------------------------
diff --git 
a/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/menu/AddExternalToolContextualMenuAction.java
 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/menu/AddExternalToolContextualMenuAction.java
new file mode 100644
index 0000000..956fd16
--- /dev/null
+++ 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/menu/AddExternalToolContextualMenuAction.java
@@ -0,0 +1,110 @@
+/*******************************************************************************
+ * 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 org.apache.taverna.activities.externaltool.menu;
+
+import java.awt.event.ActionEvent;
+import java.net.URI;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+
+import org.apache.taverna.activities.externaltool.ExternalToolActivity;
+import 
org.apache.taverna.activities.externaltool.servicedescriptions.ExternalToolTemplateServiceDescription;
+import org.apache.taverna.ui.menu.AbstractContextualMenuAction;
+import org.apache.taverna.ui.menu.MenuManager;
+import org.apache.taverna.workbench.activityicons.ActivityIconManager;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.selection.SelectionManager;
+import org.apache.taverna.workbench.ui.workflowview.WorkflowView;
+import org.apache.taverna.workflowmodel.Dataflow;
+
+import org.apache.log4j.Logger;
+
+/**
+ * An action to add an external tool + a wrapping processor to the workflow.
+ *
+ * @author Alex Nenadic
+ * @author Alan Williamns
+ *
+ */
+@SuppressWarnings("serial")
+public class AddExternalToolContextualMenuAction extends 
AbstractContextualMenuAction {
+
+       private static final String ADD_EXTERNAL_TOOL = "Tool";
+
+       private static final URI insertSection = URI
+                       
.create("http://taverna.sf.net/2009/contextMenu/insert";);
+
+       private static Logger logger = 
Logger.getLogger(AddExternalToolMenuAction.class);
+
+       private EditManager editManager;
+
+       private MenuManager menuManager;
+
+       private SelectionManager selectionManager;
+
+       private ActivityIconManager activityIconManager;
+
+       public AddExternalToolContextualMenuAction() {
+               super(insertSection, 900);
+       }
+
+       @Override
+       public boolean isEnabled() {
+               return super.isEnabled() && 
getContextualSelection().getSelection() instanceof Dataflow;
+       }
+
+       @Override
+       protected Action createAction() {
+
+               return new AddExternalToolAction();
+       }
+
+       protected class AddExternalToolAction extends AbstractAction {
+               AddExternalToolAction() {
+                       super(ADD_EXTERNAL_TOOL, 
activityIconManager.iconForActivity(
+                                       new ExternalToolActivity()));
+               }
+
+               public void actionPerformed(ActionEvent e) {
+                       WorkflowView.importServiceDescription(
+                                       
ExternalToolTemplateServiceDescription.getServiceDescription(), false,
+                                       editManager, menuManager, 
selectionManager);
+               }
+       }
+
+       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;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/163747de/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/menu/AddExternalToolMenuAction.java
----------------------------------------------------------------------
diff --git 
a/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/menu/AddExternalToolMenuAction.java
 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/menu/AddExternalToolMenuAction.java
new file mode 100644
index 0000000..2877fcb
--- /dev/null
+++ 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/menu/AddExternalToolMenuAction.java
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * 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 org.apache.taverna.activities.externaltool.menu;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.InputEvent;
+import java.awt.event.KeyEvent;
+import java.net.URI;
+
+import javax.swing.Action;
+import javax.swing.KeyStroke;
+
+import org.apache.taverna.activities.externaltool.ExternalToolActivity;
+import 
org.apache.taverna.activities.externaltool.servicedescriptions.ExternalToolTemplateServiceDescription;
+import org.apache.taverna.ui.menu.AbstractMenuAction;
+import org.apache.taverna.ui.menu.DesignOnlyAction;
+import org.apache.taverna.ui.menu.MenuManager;
+import org.apache.taverna.workbench.activityicons.ActivityIconManager;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.selection.SelectionManager;
+import org.apache.taverna.workbench.ui.workflowview.WorkflowView;
+import org.apache.taverna.workbench.views.graph.menu.InsertMenu;
+
+import org.apache.log4j.Logger;
+
+/**
+ * An action to add a externaltool activity + a wrapping processor to the 
workflow.
+ *
+ * @author Alex Nenadic
+ * @author alanrw
+ *
+ */
+@SuppressWarnings("serial")
+public class AddExternalToolMenuAction extends AbstractMenuAction {
+
+       private static final String ADD_EXTERNAL_TOOL = "Tool";
+
+       private static final URI ADD_EXTERNAL_TOOL_URI = URI
+       
.create("http://taverna.sf.net/2008/t2workbench/menu#graphMenuAddExternalTool";);
+
+       private static Logger logger = Logger
+                       .getLogger(AddExternalToolMenuAction.class);
+
+       private EditManager editManager;
+       private MenuManager menuManager;
+       private SelectionManager selectionManager;
+
+       private ActivityIconManager activityIconManager;
+
+       public AddExternalToolMenuAction() {
+               super(InsertMenu.INSERT, 900, ADD_EXTERNAL_TOOL_URI);
+       }
+
+       @Override
+       protected Action createAction() {
+
+               return new AddExternalToolAction();
+       }
+
+       protected class AddExternalToolAction extends DesignOnlyAction {
+               AddExternalToolAction () {
+                       super ();
+                       putValue(SMALL_ICON, 
activityIconManager.iconForActivity(
+                                       new ExternalToolActivity()));
+                       putValue(NAME, ADD_EXTERNAL_TOOL);
+                       putValue(SHORT_DESCRIPTION, "Tool");
+                       putValue(Action.ACCELERATOR_KEY,
+                                       KeyStroke.getKeyStroke(KeyEvent.VK_T, 
InputEvent.SHIFT_DOWN_MASK | InputEvent.ALT_DOWN_MASK));
+               }
+
+               public void actionPerformed(ActionEvent e) {
+                       
WorkflowView.importServiceDescription(ExternalToolTemplateServiceDescription.getServiceDescription(),
+                       false, editManager, menuManager, selectionManager);
+               }
+       }
+
+       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;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/163747de/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/menu/ConfigureExternalToolMenuAction.java
----------------------------------------------------------------------
diff --git 
a/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/menu/ConfigureExternalToolMenuAction.java
 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/menu/ConfigureExternalToolMenuAction.java
new file mode 100644
index 0000000..5f8b1bd
--- /dev/null
+++ 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/menu/ConfigureExternalToolMenuAction.java
@@ -0,0 +1,69 @@
+/*******************************************************************************
+ * Copyright (C) 2010 Hajo Nils Krabbenhoeft, spratpix GmbH & Co. KG
+ *
+ *  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 org.apache.taverna.activities.externaltool.menu;
+
+import javax.swing.Action;
+
+import org.apache.taverna.activities.externaltool.ExternalToolActivity;
+import 
org.apache.taverna.activities.externaltool.actions.ExternalToolActivityConfigureAction;
+import org.apache.taverna.workbench.activityicons.ActivityIconManager;
+import 
org.apache.taverna.workbench.activitytools.AbstractConfigureActivityMenuAction;
+import org.apache.taverna.workbench.edits.EditManager;
+import org.apache.taverna.workbench.file.FileManager;
+
+/**
+ * This class adds the plugin configuration action to the context menu of 
every use case activity.
+ *
+ * @author Hajo Nils Krabbenhoeft
+ */
+public class ConfigureExternalToolMenuAction extends
+               AbstractConfigureActivityMenuAction<ExternalToolActivity> {
+
+       private EditManager editManager;
+       private FileManager fileManager;
+       private ActivityIconManager activityIconManager;
+
+       public ConfigureExternalToolMenuAction() {
+               super(ExternalToolActivity.class);
+       }
+
+       @Override
+       protected Action createAction() {
+               ExternalToolActivityConfigureAction configAction = new 
ExternalToolActivityConfigureAction(
+                               findActivity(), getParentFrame(), editManager, 
fileManager, activityIconManager);
+               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;
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/163747de/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/menu/FeedbackMenuAction.java
----------------------------------------------------------------------
diff --git 
a/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/menu/FeedbackMenuAction.java
 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/menu/FeedbackMenuAction.java
new file mode 100644
index 0000000..e85c0e4
--- /dev/null
+++ 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/menu/FeedbackMenuAction.java
@@ -0,0 +1,82 @@
+/*******************************************************************************
+ * Copyright (C) 2010 Hajo Nils Krabbenhoeft, spratpix GmbH & Co. KG
+ *
+ *  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 org.apache.taverna.activities.externaltool.menu;
+
+import java.awt.Desktop;
+import java.awt.event.ActionEvent;
+import java.io.IOException;
+import java.net.URI;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.Icon;
+import javax.swing.JOptionPane;
+
+import org.apache.taverna.ui.menu.AbstractMenuAction;
+
+import org.apache.log4j.Logger;
+
+/**
+ * This class adds the feedback item to the context menu of every use case
+ * activity.
+ *
+ * @author Hajo Nils Krabbenhoeft
+ */
+public class FeedbackMenuAction extends AbstractMenuAction {
+
+       private static Logger logger = 
Logger.getLogger(FeedbackMenuAction.class);
+
+
+       private static final URI feedbackSection = 
URI.create("http://taverna.sf.net/2009/contextMenu/configure";);
+
+       public FeedbackMenuAction() {
+               super(feedbackSection, 51);
+       }
+
+       protected Action createAction() {
+           // final ImageIcon icon = 
KnowARCConfigurationFactory.getConfiguration().getIcon();
+               return new SendFeedbackAction("Send Feedback...", null);
+       }
+
+       private final class SendFeedbackAction extends AbstractAction {
+               private static final long serialVersionUID = 1L;
+
+               private static final String errTitle = "Could not open web 
browser for feedback:";
+               private static final String feedbackUrl = 
"http://www.taverna.org.uk/about/contact-us/feedback?product=ExternalToolService";;
+
+               private SendFeedbackAction(String name, Icon icon) {
+                       super(name, icon);
+               }
+
+               public void actionPerformed(ActionEvent e) {
+                       if (Desktop.isDesktopSupported()) {
+                               try {
+                                       
Desktop.getDesktop().browse(URI.create(feedbackUrl));
+                               } catch (IOException e1) {
+                                       JOptionPane.showMessageDialog(null, 
feedbackUrl + "\n" + e1.getLocalizedMessage(), errTitle, 
JOptionPane.ERROR_MESSAGE);
+                               }
+                       } else {
+                               JOptionPane.showMessageDialog(null, "Go to " + 
feedbackUrl, errTitle, JOptionPane.ERROR_MESSAGE);
+                       }
+               }
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/163747de/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/servicedescriptions/AddExternalToolServiceDialog.java
----------------------------------------------------------------------
diff --git 
a/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/servicedescriptions/AddExternalToolServiceDialog.java
 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/servicedescriptions/AddExternalToolServiceDialog.java
new file mode 100644
index 0000000..88d6afe
--- /dev/null
+++ 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/servicedescriptions/AddExternalToolServiceDialog.java
@@ -0,0 +1,189 @@
+/*******************************************************************************
+ * Copyright (C) 2007 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 org.apache.taverna.activities.externaltool.servicedescriptions;
+
+import java.awt.BorderLayout;
+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.KeyEvent;
+import java.io.IOException;
+import java.net.URL;
+import java.net.URLConnection;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.border.EmptyBorder;
+
+import org.apache.taverna.workbench.MainWindow;
+import org.apache.taverna.workbench.helper.HelpEnabledDialog;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Dialog that lets user specify a URL of a Tool service they want 
+ * to add to the Service Panel. In the case the Tool URL is behind
+ * HTTPS or service's endpoints require HTTPS it will ask user to confirm
+ * if they want to trust it. 
+ * 
+ * @author Alex Nenadic
+ *
+ */
+@SuppressWarnings("serial")
+public abstract class AddExternalToolServiceDialog extends HelpEnabledDialog {
+
+       private JTextField toolLocationField;
+       private Logger logger = 
Logger.getLogger(AddExternalToolServiceDialog.class);
+
+       public AddExternalToolServiceDialog()  {
+               super(MainWindow.getMainWindow(), "Add tool service", true, 
null); // create a non-modal dialog
+               initComponents();
+               setLocationRelativeTo(getParent());
+       }
+
+       private void initComponents() {
+               JPanel mainPanel = new JPanel(new GridBagLayout());
+               mainPanel.setBorder(new EmptyBorder(10,10,10,10));
+               
+               JLabel toolLocatitionLabel = new JLabel("Tool registry 
location",ExternalToolActivityIcon.getExternalToolIcon(), JLabel.LEFT);         
 
+               GridBagConstraints gbc = new GridBagConstraints();
+               gbc.weighty = 0.0;
+               
+               gbc.weightx = 0.0;
+               gbc.gridx = 0;
+               gbc.gridy = 0;
+               gbc.fill = GridBagConstraints.NONE;
+               gbc.anchor = GridBagConstraints.WEST;
+               gbc.insets = new Insets(5, 10, 0, 0);
+               mainPanel.add(toolLocatitionLabel, gbc);
+        
+               toolLocationField = new 
JTextField("http://taverna.nordugrid.org/sharedRepository/xml.php";);
+               gbc.weightx = 1.0;
+               gbc.gridx = 1;
+               gbc.gridy = 0;
+               gbc.fill = GridBagConstraints.HORIZONTAL;
+               gbc.anchor = GridBagConstraints.WEST;
+               gbc.insets = new Insets(5, 10, 0, 5);           
+               mainPanel.add(toolLocationField, gbc);
+               
+           final JButton addServiceButton = new JButton("Add");
+           addServiceButton.addActionListener(new ActionListener()
+               {
+                   public void actionPerformed(ActionEvent evt)
+                   {
+                       addPressed();
+                   }
+               });
+           
+           // When user presses "Return" key fire the action on the "Add" 
button
+           addServiceButton.addKeyListener(new java.awt.event.KeyAdapter() {
+                       public void keyPressed(java.awt.event.KeyEvent evt) {
+                               if (evt.getKeyCode() == KeyEvent.VK_ENTER) {
+                                       addPressed();
+                               }
+                       }
+               });
+               getRootPane().setDefaultButton(addServiceButton);
+           
+        JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
+        buttonsPanel.add(addServiceButton);
+        
+        getContentPane().setLayout(new BorderLayout());
+        getContentPane().add(mainPanel, BorderLayout.CENTER);
+        getContentPane().add(buttonsPanel, BorderLayout.SOUTH);
+        
+               setSize(getPreferredSize());
+        pack();
+       }
+       
+    /**
+     * 'Add service' button pressed or otherwise activated.
+     */
+    private void addPressed()
+    {
+               final String toolURLString = toolLocationField.getText().trim();
+               new Thread("Adding tool " + toolURLString) {
+                       public void run() {
+                               // Only add the service provider for this 
service if service URL
+                               // starts with 'http'
+                               // or if it starts with 'https' and user 
explicitly said they
+                               // wanted to trust this service.
+                               /*
+                                * if (shouldTrust(toolURLString)){ 
addRegistry(toolURLString);
+                                * }
+                                */
+                               try {
+                                       URL url = new URL(toolURLString);
+                                       URLConnection connection = 
url.openConnection();
+                                       try {
+                                               // If the url starts with 
'https' - security hook for
+                                               // https connection's trust 
manager
+                                               // will be engaged and user 
will be asked automatically
+                                               // if they want
+                                               // to trust the connection (if 
it is not already
+                                               // trusted). If the urls starts 
with 'http' -
+                                               // this will not have any 
effect apart from checking if
+                                               // we can open a connection.
+                                               connection.connect(); // if 
this does not fail - add the
+                                               // tool
+                                               // service provider for this 
service to
+                                               // the registry
+                                       } finally {
+                                               try {
+                                                       
connection.getInputStream().close();
+                                               } catch (IOException ex) {
+                                               }
+                                       }
+                                       addRegistry(toolURLString);
+                               } catch (Exception ex) { // anything failed
+                                       JOptionPane.showMessageDialog(null,
+                                                       "Could not read the 
tool descriptions from "
+                                                                       + 
toolURLString + ":\n" + ex,
+                                                       "Could not add tool 
service",
+                                                       
JOptionPane.ERROR_MESSAGE);
+
+                                       logger.error(
+                                                       "Failed to add tool 
description provider for service: "
+                                                                       + 
toolURLString, ex);
+
+                               }
+                       };
+               }.start();
+               closeDialog();
+    }
+
+       protected abstract void addRegistry(String tool);       
+       
+       /**
+        * Closes the dialog.
+        */
+       private void closeDialog() {
+               setVisible(false);
+               dispose();
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench-common-activities/blob/163747de/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/servicedescriptions/ExternalToolActivityIcon.java
----------------------------------------------------------------------
diff --git 
a/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/servicedescriptions/ExternalToolActivityIcon.java
 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/servicedescriptions/ExternalToolActivityIcon.java
new file mode 100644
index 0000000..214285d
--- /dev/null
+++ 
b/taverna-external-tool-activity-ui/src/main/java/org/apache/taverna/activities/externaltool/servicedescriptions/ExternalToolActivityIcon.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (C) 2009 Hajo Nils Krabbenhoeft, INB, University of Luebeck
+ *
+ *  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 org.apache.taverna.activities.externaltool.servicedescriptions;
+
+import java.awt.Color;
+
+import javax.swing.Icon;
+import javax.swing.ImageIcon;
+
+import org.apache.taverna.activities.externaltool.ExternalToolActivity;
+import org.apache.taverna.workbench.activityicons.ActivityIconSPI;
+import org.apache.taverna.workbench.configuration.colour.ColourManager;
+import org.apache.taverna.workflowmodel.processor.activity.Activity;
+
+/**
+ * This class provides an icon for the use case activity.
+ *
+ * @author Hajo Nils Krabbenhoeft
+ */
+public class ExternalToolActivityIcon implements ActivityIconSPI {
+
+       private static final String PROCESSOR_COLOUR_STRING = "#F28C55";
+
+       private static Icon icon;
+
+       public int canProvideIconScore(Activity<?> activity) {
+               if 
(activity.getClass().getName().equals(ExternalToolActivity.class.getName()))
+                       return DEFAULT_ICON + 1;
+               else
+                       return NO_ICON;
+       }
+
+       public Icon getIcon(Activity<?> activity) {
+               return getExternalToolIcon();
+       }
+
+       public static Icon getExternalToolIcon() {
+               if (icon == null) {
+                       icon = new 
ImageIcon(ExternalToolActivityIcon.class.getResource("/externaltool.png"));
+               }
+               return icon;
+       }
+
+       public static String getColourString() {
+               return PROCESSOR_COLOUR_STRING;
+       }
+
+       public void setColourManager(ColourManager colourManager) {
+               // set colour for XPath processors in the workflow diagram
+               
colourManager.setPreferredColour(ExternalToolActivity.class.getCanonicalName(),
+                               Color.decode(PROCESSOR_COLOUR_STRING));
+       }
+
+}

Reply via email to