You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@taverna.apache.org by re...@apache.org on 2015/03/19 14:44:00 UTC

[32/35] incubator-taverna-common-activities git commit: package names changed to org.apache.taverna.*

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/433612be/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/ExternalToolActivityConfigurationBean.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/ExternalToolActivityConfigurationBean.java b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/ExternalToolActivityConfigurationBean.java
new file mode 100644
index 0000000..c392310
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/ExternalToolActivityConfigurationBean.java
@@ -0,0 +1,213 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.externaltool;
+
+import java.util.List;
+
+import org.apache.taverna.activities.externaltool.manager.InvocationGroup;
+import org.apache.taverna.activities.externaltool.manager.InvocationMechanism;
+import org.apache.taverna.activities.externaltool.manager.MechanismCreator;
+import net.sf.taverna.t2.workflowmodel.processor.config.ConfigurationBean;
+import net.sf.taverna.t2.workflowmodel.processor.config.ConfigurationProperty;
+import de.uni_luebeck.inb.knowarc.usecases.UseCaseDescription;
+
+@ConfigurationBean(uri = ExternalToolActivity.URI + "#Config")
+public final class ExternalToolActivityConfigurationBean {
+
+	private InvocationGroup group;
+
+	private String mechanismType;
+
+	private String mechanismName;
+
+	private String mechanismXML;
+
+	private transient InvocationMechanism mechanism;
+
+	protected String repositoryUrl;
+	protected String externaltoolid;
+	protected UseCaseDescription useCaseDescription = null;
+	private boolean edited = false;
+
+	private List<MechanismCreator> mechanismCreators;
+
+    public boolean isEdited() {
+		return edited;
+	}
+
+	public ExternalToolActivityConfigurationBean() {
+	}
+
+	public InvocationGroup getInvocationGroup() {
+	    return group;
+	}
+
+	@ConfigurationProperty(name = "invocationGroup", label = "InvocationGroup", required=false)
+	public void setInvocationGroup(
+			InvocationGroup group) {
+		this.group = group;
+		clearMechanismInformation();
+	}
+
+	private void clearMechanismInformation() {
+		this.mechanismType = null;
+		this.mechanismName = null;
+		this.mechanismXML = null;
+		this.mechanism = null;
+	}
+
+	/**
+	 * @return the repositoryUrl
+	 */
+	public String getRepositoryUrl() {
+		return repositoryUrl;
+	}
+
+	/**
+	 * @param repositoryUrl the repositoryUrl to set
+	 */
+	@ConfigurationProperty(name = "repositoryUrl", label = "Repository URL", required=false)
+	public void setRepositoryUrl(String repositoryUrl) {
+		this.repositoryUrl = repositoryUrl;
+	}
+
+	/**
+	 * @return the externaltoolid
+	 */
+	public String getExternaltoolid() {
+		return externaltoolid;
+	}
+
+	/**
+	 * @param externaltoolid the externaltoolid to set
+	 */
+	@ConfigurationProperty(name = "toolId", label = "Tool ID")
+	public void setExternaltoolid(String externaltoolid) {
+		this.externaltoolid = externaltoolid;
+	}
+
+	/**
+	 * @return the useCaseDescription
+	 */
+	public UseCaseDescription getUseCaseDescription() {
+		return useCaseDescription;
+	}
+
+	/**
+	 * @param useCaseDescription the useCaseDescription to set
+	 */
+	@ConfigurationProperty(name = "toolDescription", label = "Tool Description")
+	public void setUseCaseDescription(UseCaseDescription useCaseDescription) {
+		this.useCaseDescription = useCaseDescription;
+	}
+
+	@ConfigurationProperty(name = "edited", label = "Edited", required=false)
+	public void setEdited(boolean b) {
+		this.edited  = b;
+	}
+
+	/**
+	 * Note this also sets the details
+	 *
+	 * @param mechanism the mechanism to set
+	 */
+	public void setMechanism(InvocationMechanism mechanism) {
+		this.mechanism = mechanism;
+		convertMechanismToDetails();
+		this.group = null;
+	}
+
+	public void convertMechanismToDetails() {
+		if (mechanism != null) {
+			this.setMechanismXML(mechanism.getXML());
+			this.setMechanismName(mechanism.getName());
+			this.setMechanismType(mechanism.getType());
+		}
+	}
+
+	/**
+	 * @param mechanismType the mechanismType to set
+	 */
+	@ConfigurationProperty(name = "mechanismType", label = "Mechanism Type", required=false)
+	public void setMechanismType(String mechanismType) {
+		this.mechanismType = mechanismType;
+	}
+
+	/**
+	 * @param mechanismName the mechanismName to set
+	 */
+	@ConfigurationProperty(name = "mechanismName", label = "Mechanism Name", required=false)
+	public void setMechanismName(String mechanismName) {
+		this.mechanismName = mechanismName;
+	}
+
+	/**
+	 * @param mechanismXML the mechanismXML to set
+	 */
+	@ConfigurationProperty(name = "mechanismXML", label = "Mechanism XML", required=false)
+	public void setMechanismXML(String mechanismXML) {
+		this.mechanismXML = mechanismXML;
+	}
+
+	public void convertDetailsToMechanism() {
+		if (mechanismXML != null) {
+			for (MechanismCreator mc : mechanismCreators) {
+				if (mc.canHandle(getMechanismType())) {
+					mechanism = mc.convert(getMechanismXML(), getMechanismName());
+					break;
+				}
+			}
+		}
+	}
+
+	/**
+	 * @return the mechanism
+	 */
+	public InvocationMechanism getMechanism() {
+
+		return mechanism;
+	}
+
+	/**
+	 * @return the mechanismType
+	 */
+	public String getMechanismType() {
+		return mechanismType;
+	}
+
+	/**
+	 * @return the mechanismName
+	 */
+	public String getMechanismName() {
+		return mechanismName;
+	}
+
+	/**
+	 * @return the mechanismXML
+	 */
+	public String getMechanismXML() {
+		return mechanismXML;
+	}
+
+	public void setMechanismCreators(List<MechanismCreator> mechanismCreators) {
+		this.mechanismCreators = mechanismCreators;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/433612be/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/ExternalToolActivityFactory.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/ExternalToolActivityFactory.java b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/ExternalToolActivityFactory.java
new file mode 100644
index 0000000..94c0fe8
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/ExternalToolActivityFactory.java
@@ -0,0 +1,99 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.externaltool;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.List;
+import java.util.Set;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import org.apache.taverna.activities.externaltool.manager.MechanismCreator;
+import net.sf.taverna.t2.workflowmodel.Edits;
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityConfigurationException;
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityFactory;
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityInputPort;
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityOutputPort;
+
+/**
+ * An {@link ActivityFactory} for creating <code>ExternalToolActivity</code>.
+ *
+ * @author David Withers
+ */
+public class ExternalToolActivityFactory implements ActivityFactory {
+
+	private List<InvocationCreator> invocationCreators;
+
+	private List<MechanismCreator> mechanismCreators;
+
+        private Edits edits;
+
+	@Override
+	public ExternalToolActivity createActivity() {
+		ExternalToolActivity activity = new ExternalToolActivity();
+		activity.setInvocationCreators(invocationCreators);
+                activity.setEdits(edits);
+		return activity;
+	}
+
+	@Override
+	public URI getActivityType() {
+		return URI.create(ExternalToolActivity.URI);
+	}
+
+	@Override
+	public JsonNode getActivityConfigurationSchema() {
+		ObjectMapper objectMapper = new ObjectMapper();
+		try {
+ 			return objectMapper.readTree(getClass().getResource("/schema.json"));
+		} catch (IOException e) {
+			return objectMapper.createObjectNode();
+		}
+	}
+
+	public void setInvocationCreators(List<InvocationCreator> invocationCreators) {
+		this.invocationCreators = invocationCreators;
+	}
+
+	public void setMechanismCreators(List<MechanismCreator> mechanismCreators) {
+		this.mechanismCreators = mechanismCreators;
+	}
+
+	@Override
+	public Set<ActivityInputPort> getInputPorts(JsonNode configuration)
+			throws ActivityConfigurationException {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+	@Override
+	public Set<ActivityOutputPort> getOutputPorts(JsonNode configuration)
+			throws ActivityConfigurationException {
+		// TODO Auto-generated method stub
+		return null;
+	}
+
+        public void setEdits(Edits edits) {
+		this.edits = edits;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/433612be/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/ExternalToolActivityHealthChecker.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/ExternalToolActivityHealthChecker.java b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/ExternalToolActivityHealthChecker.java
new file mode 100644
index 0000000..a3e3fb2
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/ExternalToolActivityHealthChecker.java
@@ -0,0 +1,193 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.externaltool;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+
+import org.apache.taverna.activities.externaltool.manager.InvocationGroup;
+import org.apache.taverna.activities.externaltool.manager.InvocationGroupManager;
+import org.apache.taverna.activities.externaltool.manager.InvocationMechanism;
+import net.sf.taverna.t2.visit.VisitReport;
+import net.sf.taverna.t2.visit.VisitReport.Status;
+import net.sf.taverna.t2.workflowmodel.health.HealthCheck;
+import net.sf.taverna.t2.workflowmodel.health.HealthChecker;
+import net.sf.taverna.t2.workflowmodel.utils.Tools;
+
+public class ExternalToolActivityHealthChecker implements HealthChecker<ExternalToolActivity> {
+
+	private InvocationGroupManager invocationGroupManager;
+	private ExternalToolActivity activity;
+
+	public boolean canVisit(Object subject) {
+		return subject != null && subject instanceof ExternalToolActivity;
+	}
+
+	public VisitReport visit(ExternalToolActivity activity, List<Object> ancestry) {
+		this.activity = activity;
+		ExternalToolActivityConfigurationBean configuration = activity.getConfigurationNoConversion();
+		List<VisitReport> reports = new ArrayList<VisitReport>();
+
+		VisitReport locationReport = checkLocation(configuration);
+		if (locationReport != null) {
+			reports.add(locationReport);
+		}
+
+		VisitReport report = new VisitReport(HealthCheck.getInstance(), activity, "External tool service", HealthCheck.NO_PROBLEM, reports);
+
+		return report;
+	}
+
+
+	private VisitReport checkLocation(
+			ExternalToolActivityConfigurationBean configuration) {
+
+		if (!updateLocation(configuration)) {
+			return new VisitReport(HealthCheck.getInstance(), activity, "Unmanaged invocation mechanism", HealthCheck.UNMANAGED_LOCATION, Status.WARNING);
+		} else {
+			return null;
+		}
+	}
+
+	public boolean updateLocation(ExternalToolActivityConfigurationBean configuration) {
+		InvocationGroup invocationGroup = configuration.getInvocationGroup();
+		String invocationGroupSpecification = null;
+		String invocationMechanismSpecification = null;
+		if (invocationGroup != null) {
+			if (invocationGroupManager.containsGroup(invocationGroup)) {
+				return true;
+			}
+			InvocationGroup replacementGroup = invocationGroupManager.getGroupReplacement(invocationGroup);
+			if (replacementGroup != null) {
+				configuration.setInvocationGroup(replacementGroup);
+				return true;
+			}
+			invocationGroupSpecification = invocationGroup.getName() + ":" + invocationGroup.getMechanismXML();
+			InvocationGroup importedGroup = invocationGroupManager.getImportedGroup(invocationGroupSpecification);
+			if (importedGroup != null) {
+				configuration.setInvocationGroup(importedGroup);
+				return true;
+			}
+		}
+
+		InvocationMechanism invocationMechanism = configuration.getMechanism();
+		if (invocationMechanism != null) {
+			if (invocationGroupManager.containsMechanism(invocationMechanism)) {
+				return true;
+			}
+		}
+		String mechanismXML = null;
+		String mechanismName = null;
+
+		if (invocationGroup != null) {
+			mechanismXML = invocationGroup.getMechanismXML();
+			mechanismName = invocationGroup.getMechanismName();
+		} else {
+			mechanismXML = configuration.getMechanismXML();
+			mechanismName = configuration.getMechanismName();
+		}
+		invocationMechanismSpecification = mechanismName + ":" + mechanismXML;
+
+		InvocationMechanism foundMechanism = null;
+		HashSet<String> mechanismNames = new HashSet<String>();
+		for (InvocationMechanism mechanism : invocationGroupManager.getMechanisms()) {
+			mechanismNames.add(mechanism.getName());
+			if (mechanism.getName().equals(mechanismName) && (mechanism.getXML().equals(mechanismXML))) {
+				if (invocationMechanism != mechanism) {
+					foundMechanism = mechanism;
+				}
+			}
+		}
+
+		if (foundMechanism == null) {
+			foundMechanism = invocationGroupManager.getMechanismReplacement(invocationMechanismSpecification);
+			if (foundMechanism == null) {
+				foundMechanism = invocationGroupManager.getImportedMechanism(invocationMechanismSpecification);
+			}
+		}
+
+		if (foundMechanism != null) {
+			if (invocationGroup != null) {
+				invocationGroup.setMechanism(foundMechanism);
+				// Cannot return because invocationGroup is still unknown
+			} else {
+				configuration.setMechanism(foundMechanism);
+				return true;
+			}
+		}
+
+		if (foundMechanism == null) {
+			InvocationMechanism createdMechanism;
+			if (invocationGroup != null) {
+				invocationGroup.convertDetailsToMechanism();
+				createdMechanism = invocationGroup.getMechanism();
+			} else {
+				configuration.convertDetailsToMechanism();
+				createdMechanism = configuration.getMechanism();
+			}
+
+			String chosenMechanismName = Tools.uniqueObjectName(mechanismName,
+					mechanismNames);
+			createdMechanism.setName(chosenMechanismName);
+			if (invocationGroup != null) {
+				invocationGroup.setMechanism(createdMechanism);
+			} else {
+				configuration.setMechanism(createdMechanism);
+			}
+			invocationGroupManager.importMechanism(invocationMechanismSpecification, createdMechanism);
+
+
+			if (invocationGroup == null) {
+				return true;
+			}
+		}
+
+		InvocationGroup foundGroup = null;
+		HashSet<String> groupNames = new HashSet<String>();
+		for (InvocationGroup group : invocationGroupManager.getInvocationGroups()) {
+			groupNames.add(group.getName());
+			if (group.getName().equals(invocationGroup.getName()) && (group.getMechanism() == invocationGroup.getMechanism())) {
+				foundGroup = group;
+			}
+		}
+		if (foundGroup != null) {
+			configuration.setInvocationGroup(foundGroup);
+			return true;
+		}
+		invocationGroup.setName(Tools.uniqueObjectName(invocationGroup.getName(), groupNames));
+		invocationGroupManager.importInvocationGroup(invocationGroupSpecification, invocationGroup);
+		return true;
+	}
+
+	public boolean isTimeConsuming() {
+		return false;
+	}
+
+	/**
+	 * Sets the invocationGroupManager.
+	 *
+	 * @param invocationGroupManager the new value of invocationGroupManager
+	 */
+	public void setInvocationGroupManager(InvocationGroupManager invocationGroupManager) {
+		this.invocationGroupManager = invocationGroupManager;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/433612be/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/ExternalToolActivityMimeTypeChecker.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/ExternalToolActivityMimeTypeChecker.java b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/ExternalToolActivityMimeTypeChecker.java
new file mode 100644
index 0000000..ab3241f
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/ExternalToolActivityMimeTypeChecker.java
@@ -0,0 +1,190 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.externaltool;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import net.sf.taverna.t2.visit.VisitReport;
+import net.sf.taverna.t2.visit.VisitReport.Status;
+import net.sf.taverna.t2.workflowmodel.Dataflow;
+import net.sf.taverna.t2.workflowmodel.Datalink;
+import net.sf.taverna.t2.workflowmodel.Merge;
+import net.sf.taverna.t2.workflowmodel.MergeInputPort;
+import net.sf.taverna.t2.workflowmodel.MergeOutputPort;
+import net.sf.taverna.t2.workflowmodel.MergePort;
+import net.sf.taverna.t2.workflowmodel.OutputPort;
+import net.sf.taverna.t2.workflowmodel.Port;
+import net.sf.taverna.t2.workflowmodel.Processor;
+import net.sf.taverna.t2.workflowmodel.ProcessorInputPort;
+import net.sf.taverna.t2.workflowmodel.ProcessorPort;
+import net.sf.taverna.t2.workflowmodel.health.HealthCheck;
+import net.sf.taverna.t2.workflowmodel.health.HealthChecker;
+import net.sf.taverna.t2.workflowmodel.processor.activity.Activity;
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityInputPort;
+import net.sf.taverna.t2.workflowmodel.processor.activity.ActivityOutputPort;
+import net.sf.taverna.t2.workflowmodel.utils.Tools;
+
+import org.apache.log4j.Logger;
+
+import de.uni_luebeck.inb.knowarc.usecases.ScriptInputUser;
+import de.uni_luebeck.inb.knowarc.usecases.ScriptOutput;
+
+/**
+ * @author alanrw
+ *
+ */
+public final class ExternalToolActivityMimeTypeChecker implements HealthChecker<ExternalToolActivity> {
+	
+	private static Logger logger = Logger.getLogger(ExternalToolActivityMimeTypeChecker.class);
+
+	public boolean canVisit(Object o) {
+		return o != null && o instanceof ExternalToolActivity;
+	}
+
+	public boolean isTimeConsuming() {
+		return false;
+	}
+
+	public VisitReport visit(ExternalToolActivity o,
+			List<Object> ancestry) {
+		List<VisitReport> reports = new ArrayList<VisitReport>();
+			Processor p = (Processor) VisitReport.findAncestor(ancestry, Processor.class);
+			Dataflow d = (Dataflow) VisitReport.findAncestor(ancestry, Dataflow.class);
+			
+			for (ActivityInputPort aip : o.getInputPorts()) {
+				Set<String> sinkMimeSet = getMimeTypesForInput(o, aip);
+				if (sinkMimeSet.isEmpty()) {
+					continue;
+				}
+				ProcessorInputPort pip = Tools.getProcessorInputPort(p, (Activity<?>) o, aip);
+				
+				for (Datalink dl : d.getLinks()) {
+
+					if (dl.getSink().equals(pip)) {
+						Port source = dl.getSource();
+						Set<VisitReport> subReports = checkSource(dl, source, d, (Activity) o, aip, sinkMimeSet);
+						for (VisitReport vr : subReports) {
+							vr.setProperty("sinkProcessor", p);
+						    vr.setProperty("activity", o);
+						    vr.setProperty("sinkPort", pip);
+						}
+						reports.addAll(subReports);
+					}
+				}
+			}
+			
+		if (reports.isEmpty()) {
+			return null;
+		}
+		if (reports.size() == 1) {
+			return reports.get(0);
+		}
+		else {
+			return new VisitReport(HealthCheck.getInstance(), o, "Collation", HealthCheck.DEFAULT_VALUE, reports);
+		}
+	}
+	
+	private Set<VisitReport> checkSource(Datalink datalink, Port source, Dataflow d, Activity o, ActivityInputPort aip, Set<String> sinkMimeSet) {
+		Set<VisitReport> reports = new HashSet<VisitReport>();
+		if (source instanceof ProcessorPort) {
+			ProcessorPort processorPort = (ProcessorPort) source;
+			Processor sourceProcessor = processorPort.getProcessor();
+			Activity sourceActivity = sourceProcessor.getActivityList().get(0);
+			if (sourceActivity instanceof ExternalToolActivity) {
+				ActivityOutputPort aop = getActivityOutputPort(sourceActivity, processorPort);
+				Set<String> sourceMimeTypes = getMimeTypesForOutput((ExternalToolActivity) sourceActivity, aop);
+				if (!sourceMimeTypes.isEmpty()) {
+					Set<String> sinkMimeTypesClone  = new HashSet<String>();
+					sinkMimeTypesClone.addAll(sinkMimeSet);
+					sinkMimeTypesClone.retainAll(sourceMimeTypes);
+					if (sinkMimeTypesClone.isEmpty()) {
+						VisitReport vr = new VisitReport(HealthCheck.getInstance(), o, "Incompatible mime types", HealthCheck.INCOMPATIBLE_MIMETYPES, Status.WARNING);
+						vr.setProperty("sourcePort", processorPort);
+						vr.setProperty("sourceProcessor", sourceProcessor);
+						vr.setProperty("link", datalink);
+						reports.add(vr);
+					}
+				}
+			}
+		} else if (source instanceof MergeOutputPort) {
+			Merge merge = ((MergePort) source).getMerge();
+			for (MergeInputPort mip : merge.getInputPorts()) {
+				for (Datalink dl : d.getLinks()) {
+					if (dl.getSink().equals(mip)) {
+						reports.addAll(checkSource(dl, dl.getSource(), d, o, aip, sinkMimeSet));
+					}
+				}
+				
+			}
+		}
+		return reports;
+	}
+	
+	private Set<String> getMimeTypesForOutput(ExternalToolActivity o, ActivityOutputPort aop) {
+		ScriptOutput so = (ScriptOutput) o.getConfiguration().getUseCaseDescription().getOutputs().get(aop.getName());
+		if (so == null) {
+			return Collections.EMPTY_SET;
+		}
+		List mimeList = Arrays.asList(so.getMime());
+		Set mimeSet = new HashSet(mimeList);
+		return mimeSet;
+	}
+
+	private Set<String> getMimeTypesForInput(ExternalToolActivity a, ActivityInputPort aip) {
+		ScriptInputUser si = (ScriptInputUser) a.getConfiguration().getUseCaseDescription().getInputs().get(aip.getName());
+		if (si == null) {
+			return Collections.EMPTY_SET;
+		}
+		ArrayList<String> mime = si.getMime();
+		if (mime != null) {
+			List mimeList = Arrays.asList(mime);
+			Set mimeSet = new HashSet(mimeList);
+		
+			return mimeSet;
+		} else {
+			return Collections.EMPTY_SET;
+		}
+	}
+	
+	private static ActivityOutputPort getActivityOutputPort(
+			Activity<?> activity, ProcessorPort processorOutputPort) {
+		ProcessorInputPort result = null;
+		for (Entry<String, String> mapEntry : activity.getOutputPortMapping()
+				.entrySet()) {
+			if (mapEntry.getKey().equals(processorOutputPort.getName())) {
+				for (OutputPort activityOutputPort : activity
+						.getOutputPorts()) {
+					if (activityOutputPort.getName().equals(mapEntry.getValue())) {
+						return (ActivityOutputPort) activityOutputPort;
+					}
+				}
+				break;
+			}
+		}
+		return null;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/433612be/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/ExternalToolRunDeletionListener.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/ExternalToolRunDeletionListener.java b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/ExternalToolRunDeletionListener.java
new file mode 100644
index 0000000..361b52f
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/ExternalToolRunDeletionListener.java
@@ -0,0 +1,54 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.externaltool;
+
+import org.apache.taverna.activities.externaltool.manager.InvocationGroupManager;
+import net.sf.taverna.t2.workflowmodel.RunDeletionListener;
+
+import org.apache.log4j.Logger;
+
+/**
+ * @author alanrw
+ *
+ */
+public class ExternalToolRunDeletionListener implements RunDeletionListener {
+
+	private static Logger logger = Logger.getLogger(ExternalToolRunDeletionListener.class);
+
+	private InvocationGroupManager invocationGroupManager;
+
+	/* (non-Javadoc)
+	 * @see net.sf.taverna.t2.workflowmodel.RunDeletionListener#deleteRun(java.lang.String)
+	 */
+	@Override
+	public void deleteRun(String runToDelete) {
+		invocationGroupManager.deleteRun(runToDelete);
+	}
+
+	/**
+	 * Sets the invocationGroupManager.
+	 *
+	 * @param invocationGroupManager the new value of invocationGroupManager
+	 */
+	public void setInvocationGroupManager(InvocationGroupManager invocationGroupManager) {
+		this.invocationGroupManager = invocationGroupManager;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/433612be/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/InvocationCreator.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/InvocationCreator.java b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/InvocationCreator.java
new file mode 100644
index 0000000..b31722d
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/InvocationCreator.java
@@ -0,0 +1,41 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.externaltool;
+
+import java.util.Map;
+
+import de.uni_luebeck.inb.knowarc.usecases.UseCaseDescription;
+import de.uni_luebeck.inb.knowarc.usecases.invocation.UseCaseInvocation;
+
+import org.apache.taverna.activities.externaltool.manager.InvocationMechanism;
+import net.sf.taverna.t2.reference.ReferenceService;
+import net.sf.taverna.t2.reference.T2Reference;
+
+/**
+ * @author alanrw
+ *
+ */
+public interface InvocationCreator {
+	
+	public boolean canHandle(String mechanismType);
+	
+	public UseCaseInvocation convert(InvocationMechanism mechanism, UseCaseDescription description, Map<String, T2Reference> data, ReferenceService referenceService);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/433612be/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/RetrieveLoginFromTaverna.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/RetrieveLoginFromTaverna.java b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/RetrieveLoginFromTaverna.java
new file mode 100644
index 0000000..45c4e54
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/RetrieveLoginFromTaverna.java
@@ -0,0 +1,76 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.externaltool;
+
+import java.net.URI;
+
+import net.sf.taverna.t2.security.credentialmanager.CMException;
+import net.sf.taverna.t2.security.credentialmanager.CredentialManager;
+import net.sf.taverna.t2.security.credentialmanager.UsernamePassword;
+import de.uni_luebeck.inb.knowarc.usecases.invocation.AskUserForPw;
+
+public class RetrieveLoginFromTaverna implements AskUserForPw {
+	private final String url;
+	private final CredentialManager credentialManager;
+
+	public RetrieveLoginFromTaverna(String url, CredentialManager credentialManager) {
+		this.url = url;
+		this.credentialManager = credentialManager;
+	}
+
+	private UsernamePassword getUserPass() {
+		try {
+			final String urlStr = url;
+			URI userpassUrl = URI.create(urlStr.replace("//", "/"));
+			final UsernamePassword userAndPass = credentialManager.getUsernameAndPasswordForService(userpassUrl, false, null);
+			return userAndPass;
+		} catch (CMException e) {
+			throw new RuntimeException("Error in Taverna Credential Manager", e);
+		}
+	}
+
+	public String getUsername() throws RuntimeException {
+		final UsernamePassword userPass = getUserPass();
+		if (userPass == null) {
+			throw new RuntimeException("Unable to obtain valid username and password");
+		}
+		userPass.resetPassword();
+		return userPass.getUsername();
+	}
+
+	public String getPassword() {
+		final UsernamePassword userPass = getUserPass();
+		final String pw = userPass.getPasswordAsString();
+		userPass.resetPassword();
+		return pw;
+	}
+
+
+	public String getKeyfile() {
+		return "";
+	}
+
+	public String getPassphrase() {
+		return "";
+	}
+
+	public void authenticationSucceeded() {
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/433612be/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/local/ExternalToolLocalInvocationMechanism.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/local/ExternalToolLocalInvocationMechanism.java b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/local/ExternalToolLocalInvocationMechanism.java
new file mode 100644
index 0000000..f846d02
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/local/ExternalToolLocalInvocationMechanism.java
@@ -0,0 +1,147 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.externaltool.local;
+
+import org.apache.taverna.activities.externaltool.manager.InvocationMechanism;
+
+import org.jdom.Element;
+import org.jdom.Text;
+
+import de.uni_luebeck.inb.knowarc.usecases.invocation.local.LocalUseCaseInvocation;
+
+/**
+ * @author alanrw
+ *
+ */
+public class ExternalToolLocalInvocationMechanism extends
+		InvocationMechanism {
+	
+	private String directory;
+	
+	private String shellPrefix;
+	
+	private String linkCommand;
+	
+	private boolean retrieveData;
+	
+	/**
+	 * 
+	 */
+	public ExternalToolLocalInvocationMechanism() {
+		super();
+		String os = System.getProperty("os.name");
+		if (!os.startsWith("Windows")) {
+			setShellPrefix(UNIX_SHELL);
+			setLinkCommand(UNIX_LINK);
+		}
+	}
+
+	@Override
+	public String getType() {
+		return LocalUseCaseInvocation.LOCAL_USE_CASE_INVOCATION_TYPE;
+	}
+
+	@Override
+	public Element getXMLElement() {
+		Element result = new Element("localInvocation");
+		if ((directory != null) && !directory.isEmpty()){
+			Element directoryElement = new Element("directory");
+			directoryElement.addContent(new Text(directory));
+			result.addContent(directoryElement);
+		}
+		if ((shellPrefix != null) && !shellPrefix.isEmpty()) {
+			Element shellPrefixElement = new Element("shellPrefix");
+			shellPrefixElement.addContent(new Text(shellPrefix));
+			result.addContent(shellPrefixElement);
+		}
+		if ((linkCommand != null) && !linkCommand.isEmpty()) {
+			Element linkCommandElement = new Element("linkCommand");
+			linkCommandElement.addContent(new Text(linkCommand));
+			result.addContent(linkCommandElement);
+		}
+		if (isRetrieveData()) {
+			Element retrieveDataElement = new Element("retrieveData");
+			result.addContent(retrieveDataElement);
+		}
+		return result;
+	}
+
+
+	/**
+	 * @return the directory
+	 */
+	public String getDirectory() {
+		return directory;
+	}
+
+	/**
+	 * @param directory the directory to set
+	 */
+	public void setDirectory(String directory) {
+		this.directory = directory;
+	}
+
+	/**
+	 * @return the shellPrefix
+	 */
+	public String getShellPrefix() {
+		return shellPrefix;
+	}
+
+	/**
+	 * @param shellPrefix the shellPrefix to set
+	 */
+	public void setShellPrefix(String shellPrefix) {
+		this.shellPrefix = shellPrefix;
+	}
+
+	/**
+	 * @return the linkCommand
+	 */
+	public String getLinkCommand() {
+		return linkCommand;
+	}
+
+	/**
+	 * @param linkCommand the linkCommand to set
+	 */
+	public void setLinkCommand(String linkCommand) {
+	    if ((linkCommand == null) || linkCommand.isEmpty()) {
+			this.linkCommand = null;
+		} else {
+			this.linkCommand = linkCommand;
+		}
+	}
+
+	/**
+	 * @return the retrieveData
+	 */
+	public boolean isRetrieveData() {
+		return retrieveData;
+	}
+
+	/**
+	 * @param retrieveData the retrieveData to set
+	 */
+	public void setRetrieveData(boolean retrieveData) {
+		this.retrieveData = retrieveData;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/433612be/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/local/LocalInvocationCreator.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/local/LocalInvocationCreator.java b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/local/LocalInvocationCreator.java
new file mode 100644
index 0000000..2ff1c70
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/local/LocalInvocationCreator.java
@@ -0,0 +1,65 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.externaltool.local;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.apache.taverna.activities.externaltool.InvocationCreator;
+import org.apache.taverna.activities.externaltool.manager.InvocationMechanism;
+import net.sf.taverna.t2.reference.ReferenceService;
+import net.sf.taverna.t2.reference.T2Reference;
+
+import org.apache.log4j.Logger;
+
+import de.uni_luebeck.inb.knowarc.usecases.UseCaseDescription;
+import de.uni_luebeck.inb.knowarc.usecases.invocation.UseCaseInvocation;
+import de.uni_luebeck.inb.knowarc.usecases.invocation.local.LocalUseCaseInvocation;
+
+/**
+ * @author alanrw
+ *
+ */
+public final class LocalInvocationCreator implements
+		InvocationCreator {
+	
+	private static Logger logger = Logger.getLogger(LocalInvocationCreator.class);
+
+	public boolean equals(Object o) {
+		return (o instanceof LocalInvocationCreator);
+	}
+
+	@Override
+	public boolean canHandle(String mechanismType) {
+		return mechanismType.equals(LocalUseCaseInvocation.LOCAL_USE_CASE_INVOCATION_TYPE);
+	}
+
+	@Override
+	public UseCaseInvocation convert(InvocationMechanism m, UseCaseDescription description, Map<String, T2Reference> data, ReferenceService referenceService) {
+	    ExternalToolLocalInvocationMechanism mechanism = (ExternalToolLocalInvocationMechanism) m;
+		UseCaseInvocation result = null;
+		try {
+		    result = new LocalUseCaseInvocation(description, mechanism.isRetrieveData(), mechanism.getDirectory(), mechanism.getShellPrefix(), mechanism.getLinkCommand());
+		} catch (IOException e) {
+			logger.error(e);
+		}
+		return result;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/433612be/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/local/LocalInvocationPersister.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/local/LocalInvocationPersister.java b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/local/LocalInvocationPersister.java
new file mode 100644
index 0000000..b30a73b
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/local/LocalInvocationPersister.java
@@ -0,0 +1,58 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.externaltool.local;
+
+import java.io.File;
+
+import org.apache.log4j.Logger;
+
+import de.uni_luebeck.inb.knowarc.usecases.invocation.local.LocalUseCaseInvocation;
+import org.apache.taverna.activities.externaltool.manager.InvocationPersister;
+
+/**
+ * @author alanrw
+ *
+ */
+public class LocalInvocationPersister extends InvocationPersister {
+	
+	private static Logger logger = Logger.getLogger(LocalInvocationPersister.class);
+
+	/* (non-Javadoc)
+	 * @see net.sf.taverna.t2.activities.externaltool.manager.InvocationPersister#load()
+	 */
+	@Override
+	public void load(File directory) {
+		LocalUseCaseInvocation.load(directory);
+	}
+
+	/* (non-Javadoc)
+	 * @see net.sf.taverna.t2.activities.externaltool.manager.InvocationPersister#persist()
+	 */
+	@Override
+	public void persist(File directory) {
+		LocalUseCaseInvocation.persist(directory);
+	}
+	
+	@Override
+	public void deleteRun(String runId) {
+			LocalUseCaseInvocation.cleanup(runId);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/433612be/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/local/LocalMechanismCreator.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/local/LocalMechanismCreator.java b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/local/LocalMechanismCreator.java
new file mode 100644
index 0000000..b92417c
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/local/LocalMechanismCreator.java
@@ -0,0 +1,64 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.externaltool.local;
+
+import org.jdom.Element;
+
+import de.uni_luebeck.inb.knowarc.usecases.invocation.local.LocalUseCaseInvocation;
+import org.apache.taverna.activities.externaltool.manager.InvocationMechanism;
+import org.apache.taverna.activities.externaltool.manager.MechanismCreator;
+
+/**
+ * @author alanrw
+ *
+ */
+public class LocalMechanismCreator extends MechanismCreator {
+
+	/* (non-Javadoc)
+	 * @see net.sf.taverna.t2.activities.externaltool.manager.MechanismCreator#canHandle(java.lang.String)
+	 */
+	@Override
+	public boolean canHandle(String mechanismType) {
+		return mechanismType.equals(LocalUseCaseInvocation.LOCAL_USE_CASE_INVOCATION_TYPE);
+	}
+
+	public InvocationMechanism convert(Element detailsElement,
+			String mechanismName) {
+		ExternalToolLocalInvocationMechanism result = new ExternalToolLocalInvocationMechanism();
+		result.setName(mechanismName);
+		Element directoryElement = detailsElement.getChild("directory");
+		if (directoryElement != null) {
+			result.setDirectory(directoryElement.getText());
+		}
+		Element shellPrefixElement = detailsElement.getChild("shellPrefix");
+		if (shellPrefixElement != null) {
+			result.setShellPrefix(shellPrefixElement.getText());
+		}
+		Element linkCommandElement = detailsElement.getChild("linkCommand");
+		if (linkCommandElement != null) {
+			result.setLinkCommand(linkCommandElement.getText());
+		}
+		Element retrieveDataElement = detailsElement.getChild("retrieveData");
+		result.setRetrieveData(retrieveDataElement != null);
+
+		return result;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/433612be/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroup.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroup.java b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroup.java
new file mode 100644
index 0000000..a811375
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroup.java
@@ -0,0 +1,157 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.externaltool.manager;
+
+import java.util.List;
+
+import org.apache.taverna.activities.externaltool.ExternalToolActivity;
+import net.sf.taverna.t2.workflowmodel.processor.config.ConfigurationBean;
+import net.sf.taverna.t2.workflowmodel.processor.config.ConfigurationProperty;
+
+import org.apache.log4j.Logger;
+
+/**
+ * @author alanrw
+ *
+ */
+@ConfigurationBean(uri = ExternalToolActivity.URI + "#InvocationGroup")
+public class InvocationGroup {
+
+	private static Logger logger = Logger.getLogger(InvocationGroup.class);
+
+	private String invocationGroupName;
+
+	private String mechanismType;
+
+	private String mechanismName;
+
+	private String mechanismXML;
+
+	private transient InvocationMechanism mechanism;
+
+	private List<MechanismCreator> mechanismCreators;
+
+	public InvocationGroup(List<MechanismCreator> mechanismCreators) {
+		setMechanismCreators(mechanismCreators);
+	}
+
+	/**
+	 * @return the invocationGroupName
+	 */
+	public String getName() {
+		return invocationGroupName;
+	}
+
+	/**
+	 * @param invocationGroupName the invocationGroupName to set
+	 */
+	@ConfigurationProperty(name = "name", label = "Invocation Group Name")
+	public void setName(String invocationGroupName) {
+		this.invocationGroupName = invocationGroupName;
+	}
+
+	/**
+	 * @return the mechanismType
+	 */
+	public String getMechanismType() {
+		return mechanismType;
+	}
+
+	/**
+	 * @param mechanismType the mechanismType to set
+	 */
+	@ConfigurationProperty(name = "mechanismType", label = "Mechanism Type")
+	public void setMechanismType(String mechanismType) {
+		this.mechanismType = mechanismType;
+	}
+
+	/**
+	 * @return the mechanismName
+	 */
+	public String getMechanismName() {
+		return mechanismName;
+	}
+
+	/**
+	 * @param mechanismName the mechanismName to set
+	 */
+	@ConfigurationProperty(name = "mechanismName", label = "Mechanism Name")
+	public void setMechanismName(String mechanismName) {
+		this.mechanismName = mechanismName;
+	}
+
+	/**
+	 * @return the mechanismXML
+	 */
+	public String getMechanismXML() {
+		return mechanismXML;
+	}
+
+	/**
+	 * @param mechanismXML the mechanismXML to set
+	 */
+	@ConfigurationProperty(name = "mechanismXML", label = "Mechanism XML")
+	public void setMechanismXML(String mechanismXML) {
+		this.mechanismXML = mechanismXML;
+	}
+
+	/**
+	 * @return the mechanism
+	 */
+	public InvocationMechanism getMechanism() {
+		return mechanism;
+	}
+
+	/**
+	 * Note this also sets the corresponding details
+	 *
+	 * @param mechanism the mechanism to set
+	 */
+	public void setMechanism(InvocationMechanism mechanism) {
+		this.mechanism = mechanism;
+		convertMechanismToDetails();
+	}
+
+	public String toString() {
+		return getName();
+	}
+
+	public void convertMechanismToDetails() {
+		this.setMechanismXML(mechanism.getXML());
+		this.setMechanismName(mechanism.getName());
+		this.setMechanismType(mechanism.getType());
+	}
+
+	public void convertDetailsToMechanism() {
+		if (mechanismXML != null) {
+			for (MechanismCreator mc : mechanismCreators) {
+				if (mc.canHandle(getMechanismType())) {
+					mechanism = mc.convert(getMechanismXML(), getMechanismName());
+					break;
+				}
+			}
+		}
+	}
+
+	public void setMechanismCreators(List<MechanismCreator> mechanismCreators) {
+		this.mechanismCreators = mechanismCreators;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/433612be/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupAddedEvent.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupAddedEvent.java b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupAddedEvent.java
new file mode 100644
index 0000000..45c7d5f
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupAddedEvent.java
@@ -0,0 +1,37 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.externaltool.manager;
+
+public class InvocationGroupAddedEvent extends InvocationManagerEvent {
+	
+	private InvocationGroup addedGroup;
+	
+	public InvocationGroupAddedEvent(InvocationGroup addedGroup) {
+		this.addedGroup = addedGroup;
+	}
+
+	/**
+	 * @return the addedGroup
+	 */
+	public InvocationGroup getAddedGroup() {
+		return addedGroup;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/433612be/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupChangedEvent.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupChangedEvent.java b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupChangedEvent.java
new file mode 100644
index 0000000..80a33d7
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupChangedEvent.java
@@ -0,0 +1,37 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.externaltool.manager;
+
+public class InvocationGroupChangedEvent extends InvocationManagerEvent {
+	
+	private InvocationGroup changedGroup;
+	
+	public InvocationGroupChangedEvent(InvocationGroup changedGroup) {
+		this.changedGroup = changedGroup;
+	}
+
+	/**
+	 * @return the changedGroup
+	 */
+	public InvocationGroup getChangedGroup() {
+		return changedGroup;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/433612be/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupManager.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupManager.java b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupManager.java
new file mode 100644
index 0000000..d8a87f1
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupManager.java
@@ -0,0 +1,101 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.externaltool.manager;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import net.sf.taverna.t2.lang.observer.Observer;
+
+/**
+ *
+ *
+ * @author David Withers
+ */
+public interface InvocationGroupManager {
+
+	public void addInvocationGroup(InvocationGroup group);
+
+	public void replaceInvocationGroup(InvocationGroup originalGroup,
+			InvocationGroup replacementGroup);
+
+	public void removeInvocationGroup(InvocationGroup group);
+
+	public void replaceInvocationMechanism(InvocationMechanism originalMechanism,
+			InvocationMechanism replacementMechanism);
+
+	public void removeMechanism(InvocationMechanism mechanism);
+
+	public HashSet<InvocationGroup> getInvocationGroups();
+
+	public InvocationGroup getDefaultGroup();
+
+	public Set<InvocationMechanism> getMechanisms();
+
+	public void addMechanism(InvocationMechanism mechanism);
+
+	public InvocationMechanism getDefaultMechanism();
+
+	public boolean containsGroup(InvocationGroup group);
+
+	public InvocationMechanism getInvocationMechanism(String defaultMechanismName);
+
+	public void mechanismChanged(InvocationMechanism im);
+	
+	/**
+	 * Get the directory where the invocation information will be/is saved to.
+	 */
+	public File getInvocationManagerDirectory();
+
+	public void saveConfiguration();
+
+	public void groupChanged(InvocationGroup group);
+
+	public void addObserver(Observer<InvocationManagerEvent> observer);
+
+	public List<Observer<InvocationManagerEvent>> getObservers();
+
+	public void removeObserver(Observer<InvocationManagerEvent> observer);
+
+	public void deleteRun(String runId);
+
+	public void persistInvocations();
+
+	public void loadInvocations();
+
+	public boolean containsMechanism(InvocationMechanism invocationMechanism);
+
+	public InvocationGroup getGroupReplacement(InvocationGroup group);
+
+	public InvocationMechanism getMechanismReplacement(String invocationMechanismSpecification);
+
+	public InvocationGroup getImportedGroup(String groupSpecification);
+
+	public InvocationMechanism getImportedMechanism(String mechanismSpecification);
+
+	public void importMechanism(String invocationMechanismSpecification,
+			InvocationMechanism createdMechanism);
+
+	public void importInvocationGroup(String invocationGroupSpecification,
+			InvocationGroup invocationGroup);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/433612be/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupRemovedEvent.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupRemovedEvent.java b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupRemovedEvent.java
new file mode 100644
index 0000000..80101dc
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationGroupRemovedEvent.java
@@ -0,0 +1,43 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.externaltool.manager;
+
+public class InvocationGroupRemovedEvent extends InvocationManagerEvent {
+	
+	private InvocationGroup removedGroup;
+	private final InvocationGroup replacementGroup;
+	
+	public InvocationGroupRemovedEvent(InvocationGroup removedGroup, InvocationGroup replacementGroup) {
+		this.removedGroup = removedGroup;
+		this.replacementGroup = replacementGroup;
+	}
+
+	/**
+	 * @return the removedGroup
+	 */
+	public InvocationGroup getRemovedGroup() {
+		return removedGroup;
+	}
+	
+	public InvocationGroup getReplacementGroup() {
+		return replacementGroup;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/433612be/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationManagerEvent.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationManagerEvent.java b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationManagerEvent.java
new file mode 100644
index 0000000..039967d
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationManagerEvent.java
@@ -0,0 +1,24 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.externaltool.manager;
+
+public abstract class InvocationManagerEvent {
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/433612be/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationMechanism.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationMechanism.java b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationMechanism.java
new file mode 100644
index 0000000..61547eb
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationMechanism.java
@@ -0,0 +1,75 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.externaltool.manager;
+
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.output.XMLOutputter;
+
+/**
+ * @author alanrw
+ *
+ */
+public abstract class InvocationMechanism {
+	
+	protected static XMLOutputter outputter = new XMLOutputter();
+
+
+	public static String UNIX_SHELL = "/bin/sh -c";
+
+	public static String UNIX_LINK = "/bin/ln -s %%PATH_TO_ORIGINAL%% %%TARGET_NAME%%";
+	
+	public static String UNIX_COPY = "/bin/cp %%PATH_TO_ORIGINAL%% %%TARGET_NAME%%";
+	
+	
+	private String name;
+
+	public final String getXML() {
+		Document document = new Document(getXMLElement());
+		String result = null;
+		synchronized (outputter) {
+			result = outputter.outputString(document);
+		}
+		return result;
+	}
+	
+	public abstract Element getXMLElement();
+
+	public abstract String getType();
+
+	/**
+	 * @return the name
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * @param name the name to set
+	 */
+	public void setName(String name) {
+		this.name = name;
+	}
+	
+	public String toString() {
+		return getName();
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/433612be/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationMechanismAddedEvent.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationMechanismAddedEvent.java b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationMechanismAddedEvent.java
new file mode 100644
index 0000000..8d5e4bf
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationMechanismAddedEvent.java
@@ -0,0 +1,37 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.externaltool.manager;
+
+public class InvocationMechanismAddedEvent extends InvocationManagerEvent {
+	
+	private InvocationMechanism addedMechanism;
+	
+	public InvocationMechanismAddedEvent(InvocationMechanism addedMechanism) {
+		this.addedMechanism = addedMechanism;
+	}
+
+	/**
+	 * @return the addeMechanism
+	 */
+	public InvocationMechanism getAddedMechanism() {
+		return addedMechanism;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/433612be/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationMechanismChangedEvent.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationMechanismChangedEvent.java b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationMechanismChangedEvent.java
new file mode 100644
index 0000000..b0dca5a
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationMechanismChangedEvent.java
@@ -0,0 +1,37 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.externaltool.manager;
+
+public class InvocationMechanismChangedEvent extends InvocationManagerEvent {
+	
+	private InvocationMechanism changedMechanism;
+	
+	public InvocationMechanismChangedEvent(InvocationMechanism changedMechanism) {
+		this.changedMechanism = changedMechanism;
+	}
+
+	/**
+	 * @return the changedMechanism
+	 */
+	public InvocationMechanism getChangedMechanism() {
+		return changedMechanism;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/433612be/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationMechanismRemovedEvent.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationMechanismRemovedEvent.java b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationMechanismRemovedEvent.java
new file mode 100644
index 0000000..ae275d2
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationMechanismRemovedEvent.java
@@ -0,0 +1,43 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.externaltool.manager;
+
+public class InvocationMechanismRemovedEvent extends InvocationManagerEvent {
+	
+	private InvocationMechanism removedMechanism;
+	private final InvocationMechanism replacementMechanism;
+	
+	public InvocationMechanismRemovedEvent(InvocationMechanism removedMechanism, InvocationMechanism replacementMechanism) {
+		this.removedMechanism = removedMechanism;
+		this.replacementMechanism = replacementMechanism;
+	}
+
+	/**
+	 * @return the addeMechanism
+	 */
+	public InvocationMechanism getRemovedMechanism() {
+		return removedMechanism;
+	}
+	
+	public InvocationMechanism getReplacementMechanism() {
+		return replacementMechanism;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/433612be/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationPersister.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationPersister.java b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationPersister.java
new file mode 100644
index 0000000..793d054
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/InvocationPersister.java
@@ -0,0 +1,36 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.externaltool.manager;
+
+import java.io.File;
+
+/**
+ * @author alanrw
+ *
+ */
+public abstract class InvocationPersister {
+	
+	public abstract void persist(File directory);
+	
+	public abstract void load(File directory);
+
+	public abstract void deleteRun(String runId);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-common-activities/blob/433612be/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/MechanismCreator.java
----------------------------------------------------------------------
diff --git a/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/MechanismCreator.java b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/MechanismCreator.java
new file mode 100644
index 0000000..9a7f3c4
--- /dev/null
+++ b/taverna-external-tool-activity/src/main/java/org/apache/taverna/activities/externaltool/manager/MechanismCreator.java
@@ -0,0 +1,65 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.activities.externaltool.manager;
+
+import java.io.IOException;
+import java.io.StringReader;
+
+import org.apache.log4j.Logger;
+import org.jdom.Document;
+import org.jdom.Element;
+import org.jdom.JDOMException;
+import org.jdom.input.SAXBuilder;
+
+/**
+ * @author alanrw
+ *
+ */
+public abstract class MechanismCreator {
+	
+	private static SAXBuilder builder = new SAXBuilder();
+
+	private static Logger logger = Logger.getLogger(MechanismCreator.class);
+	
+	public abstract boolean canHandle(String mechanismType);
+	
+	public InvocationMechanism convert(String xml, String name) {
+		
+		Document document;
+		try {
+			synchronized (builder) {
+				document = builder.build(new StringReader(xml));
+			}
+		} catch (JDOMException e1) {
+			logger.error("Null invocation", e1);
+			return null;
+		} catch (IOException e1) {
+			logger.error("Null invocation", e1);
+			return null;
+		}
+		Element top = document.getRootElement();
+		
+		return convert(top, name);
+	}
+
+	public abstract InvocationMechanism convert(Element detailsElement,
+			String mechanismName);
+
+}