Merge branch 'README'
diff --git a/pom.xml b/pom.xml
index a8a2f24..db6a7ef 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,63 +1,141 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
 	<modelVersion>4.0.0</modelVersion>
 	<parent>
 		<groupId>net.sf.taverna.t2</groupId>
 		<artifactId>ui-activities</artifactId>
-		<version>1.3-SNAPSHOT</version>
+		<version>2.0-SNAPSHOT</version>
 	</parent>
 	<groupId>net.sf.taverna.t2.ui-activities</groupId>
 	<artifactId>localworker-activity-ui</artifactId>
+	<packaging>bundle</packaging>
 	<name>Taverna 2 Localworker Activity UI</name>
 	<dependencies>
 		<dependency>
+			<groupId>net.sf.taverna.t2.ui-activities</groupId>
+			<artifactId>beanshell-activity-ui</artifactId>
+			<version>${project.version}</version>
+		</dependency>
+		<dependency>
 			<groupId>net.sf.taverna.t2.ui-api</groupId>
 			<artifactId>activity-icons-api</artifactId>
 			<version>${t2.ui.api.version}</version>
 		</dependency>
 		<dependency>
-			<groupId>net.sf.taverna.t2.activities</groupId>
-			<artifactId>dependency-activity</artifactId>
-			<version>${t2.activities.version}</version>
-		</dependency>
-		<dependency>
 			<groupId>net.sf.taverna.t2.ui-api</groupId>
 			<artifactId>activity-palette-api</artifactId>
 			<version>${t2.ui.api.version}</version>
 		</dependency>
 		<dependency>
-			<groupId>net.sf.taverna.t2.ui-impl</groupId>
-			<artifactId>file-impl</artifactId>
-			<version>${t2.ui.impl.version}</version>
-			<scope>test</scope>
+			<groupId>net.sf.taverna.t2.ui-api</groupId>
+			<artifactId>edits-api</artifactId>
+			<version>${t2.ui.api.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.taverna.t2.ui-api</groupId>
+			<artifactId>file-api</artifactId>
+			<version>${t2.ui.api.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.taverna.t2.ui-api</groupId>
+			<artifactId>menu-api</artifactId>
+			<version>${t2.ui.api.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>uk.org.taverna.configuration</groupId>
+			<artifactId>taverna-app-configuration-api</artifactId>
+			<version>${taverna.configuration.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>uk.org.taverna.scufl2</groupId>
+			<artifactId>scufl2-api</artifactId>
+			<version>${scufl2.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>com.fasterxml.jackson.core</groupId>
+			<artifactId>jackson-databind</artifactId>
+			<version>2.2.2</version>
 		</dependency>
 
-		<!--  testing dependencies -->
+		<!-- category:biojava -->
+		<!-- net.sourceforge.taverna.scuflworkers.biojava.GenBankParserWorker -->
+		<!-- net.sourceforge.taverna.scuflworkers.biojava.ReverseCompWorker -->
+		<!-- net.sourceforge.taverna.scuflworkers.biojava.SwissProtParserWorker -->
+		<!-- net.sourceforge.taverna.scuflworkers.biojava.TranscribeWorker -->
 		<dependency>
-			<groupId>junit</groupId>
-			<artifactId>junit</artifactId>
-			<scope>test</scope>
+			<groupId>uk.org.mygrid.resources</groupId>
+			<artifactId>biojava</artifactId>
+			<version>1.4pre1</version>
 		</dependency>
+		<!-- category:xml -->
+		<!-- net.sourceforge.taverna.scuflworkers.xml.XPathTextWorker -->
 		<dependency>
-			<groupId>net.sf.taverna.t2.activities</groupId>
-			<artifactId>beanshell-activity</artifactId>
-			<version>${t2.activities.version}</version>
+			<groupId>org.dom4j</groupId>
+			<artifactId>com.springsource.org.dom4j</artifactId>
+			<version>${dom4j.version}</version>
 		</dependency>
+		<!-- <dependency>
+			<groupId>dom4j</groupId>
+			<artifactId>dom4j</artifactId>
+			<version>1.6</version>
+		</dependency> -->
+		<!-- category:net -->
+		<!-- org.embl.ebi.escience.scuflworkers.java.SendEmail -->
 		<dependency>
-			<groupId>net.sf.taverna.t2.activities</groupId>
-			<artifactId>localworker-activity</artifactId>
-			<version>${t2.activities.version}</version>
+			<groupId>javax.mail</groupId>
+			<artifactId>com.springsource.javax.mail</artifactId>
+			<version>${mail.version}</version>
 		</dependency>
+		<!-- <dependency>
+			<groupId>javax.mail</groupId>
+			<artifactId>mail</artifactId>
+			<version>1.4</version>
+		</dependency> -->
 		<dependency>
-			<groupId>net.sf.taverna.t2.core</groupId>
-			<artifactId>workflowmodel-impl</artifactId>
-			<version>${t2.core.version}</version>
+			<groupId>javax.activation</groupId>
+			<artifactId>com.springsource.javax.activation</artifactId>
+			<version>1.1.1</version>
 		</dependency>
+		<!-- <dependency>
+			<groupId>javax.activation</groupId>
+			<artifactId>activation</artifactId>
+			<version>1.1</version>
+		</dependency> -->
+		<!-- category:base64 -->
+		<!-- org.embl.ebi.escience.scuflworkers.java.EncodeBase64 -->
+		<!-- org.embl.ebi.escience.scuflworkers.java.DecodeBase64 -->
 		<dependency>
-			<groupId>net.sf.taverna.t2.ui-activities</groupId>
-			<artifactId>beanshell-activity-ui</artifactId>
-			<version>${project.version}</version>
+			<groupId>org.apache.commons</groupId>
+			<artifactId>com.springsource.org.apache.commons.codec</artifactId>
+			<version>${commons.codec.version}</version>
 		</dependency>
+		<!-- <dependency>
+			<groupId>commons-codec</groupId>
+			<artifactId>commons-codec</artifactId>
+			<version>1.3</version>
+		</dependency> -->
 	</dependencies>
+	<repositories>
+		<repository>
+			<releases />
+			<snapshots>
+				<enabled>false</enabled>
+			</snapshots>
+			<id>mygrid-repository</id>
+			<name>myGrid Repository</name>
+			<url>http://www.mygrid.org.uk/maven/repository
+			</url>
+		</repository>
+		<repository>
+			<releases>
+				<enabled>false</enabled>
+			</releases>
+			<snapshots />
+			<id>mygrid-snapshot-repository</id>
+			<name>myGrid Snapshot Repository</name>
+			<url>http://www.mygrid.org.uk/maven/snapshot-repository</url>
+		</repository>
+	</repositories>
 </project>
 
diff --git a/src/main/java/net/sf/taverna/t2/activities/localworker/actions/LocalworkerActivityConfigurationAction.java b/src/main/java/net/sf/taverna/t2/activities/localworker/actions/LocalworkerActivityConfigurationAction.java
index 9d1d28b..2016ad0 100644
--- a/src/main/java/net/sf/taverna/t2/activities/localworker/actions/LocalworkerActivityConfigurationAction.java
+++ b/src/main/java/net/sf/taverna/t2/activities/localworker/actions/LocalworkerActivityConfigurationAction.java
@@ -1,19 +1,19 @@
 /*******************************************************************************
- * Copyright (C) 2007 The University of Manchester   
- * 
+ * 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
@@ -22,74 +22,70 @@
 
 import java.awt.Frame;
 import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.WindowAdapter;
-import java.awt.event.WindowEvent;
 
 import javax.swing.Action;
-import javax.swing.JDialog;
 import javax.swing.JOptionPane;
 
-import org.apache.log4j.Logger;
-
-import net.sf.taverna.t2.activities.beanshell.BeanshellActivityConfigurationBean;
-import net.sf.taverna.t2.activities.localworker.LocalworkerActivity;
-import net.sf.taverna.t2.activities.localworker.LocalworkerActivityConfigurationBean;
 import net.sf.taverna.t2.activities.localworker.views.LocalworkerActivityConfigView;
-import net.sf.taverna.t2.annotation.AnnotationAssertion;
-import net.sf.taverna.t2.annotation.AnnotationChain;
-import net.sf.taverna.t2.annotation.annotationbeans.HostInstitution;
-import net.sf.taverna.t2.lang.ui.ModelMap;
-import net.sf.taverna.t2.workbench.ModelMapConstants;
+import net.sf.taverna.t2.servicedescriptions.ServiceDescriptionRegistry;
 import net.sf.taverna.t2.workbench.activityicons.ActivityIconManager;
 import net.sf.taverna.t2.workbench.edits.EditManager;
-import net.sf.taverna.t2.workbench.helper.HelpEnabledDialog;
-import net.sf.taverna.t2.workbench.helper.Helper;
+import net.sf.taverna.t2.workbench.file.FileManager;
 import net.sf.taverna.t2.workbench.ui.actions.activity.ActivityConfigurationAction;
 import net.sf.taverna.t2.workbench.ui.views.contextualviews.activity.ActivityConfigurationDialog;
-import net.sf.taverna.t2.workflowmodel.Dataflow;
-import net.sf.taverna.t2.workflowmodel.EditException;
-import net.sf.taverna.t2.workflowmodel.EditsRegistry;
+import uk.org.taverna.configuration.app.ApplicationConfiguration;
+import uk.org.taverna.scufl2.api.activity.Activity;
+import uk.org.taverna.scufl2.api.common.Scufl2Tools;
+import uk.org.taverna.scufl2.api.configurations.Configuration;
+
+import com.fasterxml.jackson.databind.JsonNode;
 
 /**
- * The {@link LocalworkerActivity}s have pre-defined scripts, ports etc in a
- * serialised form on disk. So if the user wants to change them they have to do
- * so at own risk.
- * 
+ * The {@link LocalworkerActivity}s have pre-defined scripts, ports etc in a serialised form on
+ * disk. So if the user wants to change them they have to do so at own risk.
+ *
  * @author Ian Dunlop
- * 
  */
 @SuppressWarnings("serial")
-public class LocalworkerActivityConfigurationAction extends
-		ActivityConfigurationAction<LocalworkerActivity, BeanshellActivityConfigurationBean> {
+public class LocalworkerActivityConfigurationAction extends ActivityConfigurationAction {
 
-	private static Logger logger = Logger.getLogger(LocalworkerActivityConfigurationAction.class);
-	
 	public static final String EDIT_LOCALWORKER_SCRIPT = "Edit beanshell script";
 
-	private final Frame owner;
+	private final EditManager editManager;
 
-	public LocalworkerActivityConfigurationAction(LocalworkerActivity activity,
-			Frame owner) {
-		super(activity);
+	private final FileManager fileManager;
+
+	private final ApplicationConfiguration applicationConfiguration;
+
+	private Scufl2Tools scufl2Tools = new Scufl2Tools();
+
+	public LocalworkerActivityConfigurationAction(Activity activity, Frame owner,
+			EditManager editManager, FileManager fileManager,
+			ActivityIconManager activityIconManager,
+			ServiceDescriptionRegistry serviceDescriptionRegistry,
+			ApplicationConfiguration applicationConfiguration) {
+		super(activity, activityIconManager, serviceDescriptionRegistry);
+		this.editManager = editManager;
+		this.fileManager = fileManager;
+		this.applicationConfiguration = applicationConfiguration;
 		putValue(Action.NAME, EDIT_LOCALWORKER_SCRIPT);
-		this.owner = owner;
 	}
 
 	/**
-	 * If the localworker has not been changed it pops up a {@link JOptionPane}
-	 * warning the user that they change things at their own risk. Otherwise
-	 * just show the config view
+	 * If the localworker has not been changed it pops up a {@link JOptionPane} warning the user
+	 * that they change things at their own risk. Otherwise just show the config view
 	 */
 	public void actionPerformed(ActionEvent e) {
 		Object[] options = { "Continue", "Cancel" };
-		if (!activity.isAltered()) {
+		Configuration configuration = scufl2Tools.configurationFor(activity, activity.getParent());
+		JsonNode json = configuration.getJson();
+		if (!json.get("isAltered").booleanValue()) {
 			int n = JOptionPane
 					.showOptionDialog(
 							null,
 							"Changing the properties of a Local Worker may affect its behaviour. Do you want to continue?",
-							"WARNING", JOptionPane.YES_NO_OPTION,
-							JOptionPane.QUESTION_MESSAGE, null, // do not use a
+							"WARNING", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE,
+							null, // do not use a
 							// custom Icon
 							options, options[0]);
 
@@ -100,23 +96,22 @@
 				// do nothing
 			}
 		} else {
-			openDialog();			
+			openDialog();
 		}
 	}
 
 	private void openDialog() {
-		ActivityConfigurationDialog<LocalworkerActivity, LocalworkerActivityConfigurationBean> currentDialog = ActivityConfigurationAction.getDialog(getActivity());
+		ActivityConfigurationDialog currentDialog = ActivityConfigurationAction
+				.getDialog(getActivity());
 		if (currentDialog != null) {
 			currentDialog.toFront();
 			return;
 		}
-		final LocalworkerActivity activity = (LocalworkerActivity) getActivity();
-		final LocalworkerActivityConfigView localworkerConfigView =
-			new LocalworkerActivityConfigView(activity);
-		final ActivityConfigurationDialog dialog =
-			new ActivityConfigurationDialog (getActivity(), localworkerConfigView);
-		ActivityConfigurationAction.setDialog(getActivity(), dialog);			
+		final LocalworkerActivityConfigView localworkerConfigView = new LocalworkerActivityConfigView(
+				getActivity(), applicationConfiguration);
+		final ActivityConfigurationDialog dialog = new ActivityConfigurationDialog(getActivity(),
+				localworkerConfigView, editManager);
+		ActivityConfigurationAction.setDialog(getActivity(), dialog, fileManager);
 
-		
 	}
 }
diff --git a/src/main/java/net/sf/taverna/t2/activities/localworker/menu/ConfigureLocalworkerMenuAction.java b/src/main/java/net/sf/taverna/t2/activities/localworker/menu/ConfigureLocalworkerMenuAction.java
index ba81789..3afed8d 100644
--- a/src/main/java/net/sf/taverna/t2/activities/localworker/menu/ConfigureLocalworkerMenuAction.java
+++ b/src/main/java/net/sf/taverna/t2/activities/localworker/menu/ConfigureLocalworkerMenuAction.java
@@ -2,28 +2,61 @@
 
 import javax.swing.Action;
 
-import net.sf.taverna.t2.activities.beanshell.actions.BeanshellActivityConfigurationAction;
-import net.sf.taverna.t2.activities.localworker.LocalworkerActivity;
-import net.sf.taverna.t2.activities.localworker.actions.LocalworkerActivityConfigurationAction;
-import net.sf.taverna.t2.workbench.activitytools.AbstractConfigureActivityMenuAction;
+import uk.org.taverna.configuration.app.ApplicationConfiguration;
 
-public class ConfigureLocalworkerMenuAction extends
-		AbstractConfigureActivityMenuAction<LocalworkerActivity> {
+import net.sf.taverna.t2.activities.beanshell.actions.BeanshellActivityConfigurationAction;
+import net.sf.taverna.t2.activities.localworker.actions.LocalworkerActivityConfigurationAction;
+import net.sf.taverna.t2.activities.localworker.servicedescriptions.LocalworkerServiceDescription;
+import net.sf.taverna.t2.servicedescriptions.ServiceDescriptionRegistry;
+import net.sf.taverna.t2.ui.menu.ContextualMenuComponent;
+import net.sf.taverna.t2.ui.menu.MenuComponent;
+import net.sf.taverna.t2.workbench.activityicons.ActivityIconManager;
+import net.sf.taverna.t2.workbench.activitytools.AbstractConfigureActivityMenuAction;
+import net.sf.taverna.t2.workbench.edits.EditManager;
+import net.sf.taverna.t2.workbench.file.FileManager;
+
+public class ConfigureLocalworkerMenuAction extends AbstractConfigureActivityMenuAction implements
+		MenuComponent, ContextualMenuComponent {
+
+	private EditManager editManager;
+	private FileManager fileManager;
+	private ActivityIconManager activityIconManager;
+	private ServiceDescriptionRegistry serviceDescriptionRegistry;
+	private ApplicationConfiguration applicationConfiguration;
 
 	public ConfigureLocalworkerMenuAction() {
-		super(LocalworkerActivity.class);
+		super(LocalworkerServiceDescription.ACTIVITY_TYPE);
 	}
-	
+
 	@Override
 	protected Action createAction() {
-		LocalworkerActivity a = findActivity();
 		Action result = null;
-			result = new LocalworkerActivityConfigurationAction(
-					findActivity(), getParentFrame());
-			result.putValue(Action.NAME, BeanshellActivityConfigurationAction.EDIT_BEANSHELL_SCRIPT);
-			addMenuDots(result);
+		result = new LocalworkerActivityConfigurationAction(findActivity(), getParentFrame(),
+				editManager, fileManager, activityIconManager, serviceDescriptionRegistry,
+				applicationConfiguration);
+		result.putValue(Action.NAME, BeanshellActivityConfigurationAction.EDIT_BEANSHELL_SCRIPT);
+		addMenuDots(result);
 		return result;
 	}
 
+	public void setEditManager(EditManager editManager) {
+		this.editManager = editManager;
+	}
+
+	public void setFileManager(FileManager fileManager) {
+		this.fileManager = fileManager;
+	}
+
+	public void setActivityIconManager(ActivityIconManager activityIconManager) {
+		this.activityIconManager = activityIconManager;
+	}
+
+	public void setServiceDescriptionRegistry(ServiceDescriptionRegistry serviceDescriptionRegistry) {
+		this.serviceDescriptionRegistry = serviceDescriptionRegistry;
+	}
+
+	public void setApplicationConfiguration(ApplicationConfiguration applicationConfiguration) {
+		this.applicationConfiguration = applicationConfiguration;
+	}
 
 }
diff --git a/src/main/java/net/sf/taverna/t2/activities/localworker/servicedescriptions/LocalworkerActivityIcon.java b/src/main/java/net/sf/taverna/t2/activities/localworker/servicedescriptions/LocalworkerActivityIcon.java
index c7697ac..7d6bb5a 100644
--- a/src/main/java/net/sf/taverna/t2/activities/localworker/servicedescriptions/LocalworkerActivityIcon.java
+++ b/src/main/java/net/sf/taverna/t2/activities/localworker/servicedescriptions/LocalworkerActivityIcon.java
@@ -1,55 +1,52 @@
 /*******************************************************************************
- * Copyright (C) 2007 The University of Manchester   
- * 
+ * 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 net.sf.taverna.t2.activities.localworker.servicedescriptions;
 
+import java.net.URI;
+
 import javax.swing.Icon;
 import javax.swing.ImageIcon;
 
-import net.sf.taverna.t2.activities.localworker.LocalworkerActivity;
 import net.sf.taverna.t2.workbench.activityicons.ActivityIconSPI;
-import net.sf.taverna.t2.workflowmodel.processor.activity.Activity;
 
 /**
- * 
- * @author Alex Nenadic
  *
+ * @author Alex Nenadic
+ * @author David Withers
  */
-public class LocalworkerActivityIcon implements ActivityIconSPI{
-	
+public class LocalworkerActivityIcon implements ActivityIconSPI {
+
 	private static Icon icon;
 
-	public int canProvideIconScore(Activity<?> activity) {
-		if (activity.getClass().getName().equals(LocalworkerActivity.class.getName())) {
-			LocalworkerActivity localActivity = (LocalworkerActivity) activity;
-			if (!localActivity.isAltered()) {
-				return DEFAULT_ICON + 2;
-			}
-		}
-		return NO_ICON;
+	public int canProvideIconScore(URI activityType) {
+		if (LocalworkerServiceDescription.ACTIVITY_TYPE.equals(activityType))
+			return DEFAULT_ICON + 1;
+		else
+			return NO_ICON;
 	}
 
-	public Icon getIcon(Activity<?> activity) {
+	public Icon getIcon(URI activityType) {
 		return getLocalworkerIcon();
 	}
-	
+
 	public static Icon getLocalworkerIcon() {
 		if (icon == null) {
 			icon = new ImageIcon(LocalworkerActivityIcon.class
diff --git a/src/main/java/net/sf/taverna/t2/activities/localworker/servicedescriptions/LocalworkerServiceDescription.java b/src/main/java/net/sf/taverna/t2/activities/localworker/servicedescriptions/LocalworkerServiceDescription.java
index 35e4e76..38718b8 100644
--- a/src/main/java/net/sf/taverna/t2/activities/localworker/servicedescriptions/LocalworkerServiceDescription.java
+++ b/src/main/java/net/sf/taverna/t2/activities/localworker/servicedescriptions/LocalworkerServiceDescription.java
@@ -1,50 +1,42 @@
 package net.sf.taverna.t2.activities.localworker.servicedescriptions;
 
+import java.net.URI;
 import java.util.Arrays;
-import java.util.LinkedHashSet;
 import java.util.List;
 
 import javax.swing.Icon;
-import net.sf.taverna.raven.repository.BasicArtifact;
-import net.sf.taverna.t2.activities.beanshell.BeanshellActivityConfigurationBean;
-import net.sf.taverna.t2.activities.localworker.LocalworkerActivity;
-import net.sf.taverna.t2.activities.localworker.LocalworkerActivityConfigurationBean;
-import net.sf.taverna.t2.lang.beans.PropertyAnnotation;
-import net.sf.taverna.t2.servicedescriptions.ServiceDescription;
-import net.sf.taverna.t2.workflowmodel.processor.activity.Activity;
-import net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean;
-import net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityOutputPortDefinitionBean;
 
-public class LocalworkerServiceDescription extends ServiceDescription<BeanshellActivityConfigurationBean>{
-	
+import net.sf.taverna.t2.servicedescriptions.ServiceDescription;
+import uk.org.taverna.scufl2.api.configurations.Configuration;
+
+import com.fasterxml.jackson.databind.JsonNode;
+
+public class LocalworkerServiceDescription extends ServiceDescription {
+
+	public static final URI ACTIVITY_TYPE = URI.create("http://ns.taverna.org.uk/2010/activity/localworker");
+
 	private static final String LOCALWORKER = ServiceDescription.LOCAL_SERVICES;
 
-	private String script;
-	private List<ActivityOutputPortDefinitionBean> outputPorts;
-	private List<ActivityInputPortDefinitionBean> inputPorts;
+	private JsonNode json;
 	private String operation;
 	private String category;
 	private String provider;
-	
 	private String localworkerName;
-	public String getLocalworkerName() {
-		return localworkerName;
+
+	public JsonNode getJson() {
+		return json;
 	}
 
-	public void setLocalworkerName(String localworkerName) {
-		this.localworkerName = localworkerName;
+	public void setJson(JsonNode json) {
+		this.json = json;
 	}
 
-	private List<String> dependencies; // from old code - this property is not in use any more
-	private LinkedHashSet<BasicArtifact> artifactDependencies;
-	// Note that localworkers have no local dependencies, only artifatct ones
-
-	public String getProvider() {
-		return provider;
+	public String getOperation() {
+		return operation;
 	}
 
-	public void setProvider(String provider) {
-		this.provider = provider;
+	public void setOperation(String operation) {
+		this.operation = operation;
 	}
 
 	public String getCategory() {
@@ -55,33 +47,37 @@
 		this.category = category;
 	}
 
+	public String getProvider() {
+		return provider;
+	}
+
+	public void setProvider(String provider) {
+		this.provider = provider;
+	}
+
+	public String getLocalworkerName() {
+		return localworkerName;
+	}
+
+	public void setLocalworkerName(String localworkerName) {
+		this.localworkerName = localworkerName;
+	}
+
 	public String getType() {
 		return "Localworker";
 	}
 
 	@Override
-	public Class<? extends Activity<BeanshellActivityConfigurationBean>> getActivityClass() {
-		return LocalworkerActivity.class;
+	public URI getActivityType() {
+		return ACTIVITY_TYPE;
 	}
 
 	@Override
-	public BeanshellActivityConfigurationBean getActivityConfiguration() {
-		// TODO Auto-generated method stub
-		// different bean for each type of localworker, get xml version of bean
-		// and create BeanshellConfig
-		LocalworkerActivityConfigurationBean bean = new LocalworkerActivityConfigurationBean();
-				
-		bean.setScript(this.script);
-		bean.setInputPortDefinitions(this.inputPorts);
-		bean.setOutputPortDefinitions(this.outputPorts);
-		bean.setDependencies(this.dependencies); // this field is deprecated (replaced by artifactDependencies), but for backward compatibility we leave it here
-		// Local worker only has artifact dependencies
-		bean.setArtifactDependencies(artifactDependencies);
-		bean.setLocalworkerName(getLocalworkerName());
-		
-		// FIXME needs some mime types from the annotations (done as strings
-		// inside the port at the moment)
-		return bean;
+	public Configuration getActivityConfiguration() {
+		Configuration configuration = new Configuration();
+		configuration.setType(ACTIVITY_TYPE.resolve("#Config"));
+		configuration.setJson(getJson());
+		return configuration;
 	}
 
 	@Override
@@ -95,83 +91,15 @@
 	}
 
 	@Override
-	public List<? extends Comparable> getPath() {
+	public List<? extends Comparable<?>> getPath() {
 		List<String> result =
 		Arrays.asList (LOCALWORKER, category);
 		return result;
 	}
 
-	
-	@PropertyAnnotation(hidden=true)
-	public String getScript() {
-		return script;
-	}
-
-	public void setScript(String script) {
-		this.script = script;
-	}
-
-	public void setOutputPorts(
-			List<ActivityOutputPortDefinitionBean> outputPortBeans) {
-		this.outputPorts = outputPortBeans;
-	}
-
-	public List<ActivityOutputPortDefinitionBean> getOutputPorts() {
-		return outputPorts;
-	}
-
-	public void setInputPorts(
-			List<ActivityInputPortDefinitionBean> inputPortBeans) {
-		this.inputPorts = inputPortBeans;
-	}
-
-	public List<ActivityInputPortDefinitionBean> getInputPorts() {
-		return inputPorts;
-	}
-
-	public String getOperation() {
-		return operation;
-	}
-
-	public void setOperation(String operation) {
-		this.operation = operation;
-	}
-	///////////// From old code //////////////////
-	/**
-	 * Returns the dependencies.
-	 *
-	 * @return the dependencies
-	 */
-	public List<String> getDependencies() {
-		return dependencies;
-	}
-
-	/**
-	 * Sets the dependencies.
-	 *
-	 * @param dependencies the new dependencies
-	 */
-	public void setDependencies(List<String> dependencies) {
-		this.dependencies = dependencies;
-	}
-	///////////// From old code /////////////////
-	/**
-	 * @return the artifactDependencies
-	 */
-	public LinkedHashSet<BasicArtifact> getArtifactDependencies() {
-		return artifactDependencies;
-	}
-	
-	/**
-	 * @param artifactDependencies the artifactDependencies to set
-	 */
-	public void setArtifactDependencies(LinkedHashSet<BasicArtifact> artifactDependencies) {
-		this.artifactDependencies = artifactDependencies;
-	}
-
 	@Override
 	protected List<Object> getIdentifyingData() {
-		return Arrays.<Object>asList(getScript());
+		return Arrays.<Object>asList(getJson());
 	}
 
 }
diff --git a/src/main/java/net/sf/taverna/t2/activities/localworker/servicedescriptions/LocalworkerServiceProvider.java b/src/main/java/net/sf/taverna/t2/activities/localworker/servicedescriptions/LocalworkerServiceProvider.java
index 0b5119d..42345db 100644
--- a/src/main/java/net/sf/taverna/t2/activities/localworker/servicedescriptions/LocalworkerServiceProvider.java
+++ b/src/main/java/net/sf/taverna/t2/activities/localworker/servicedescriptions/LocalworkerServiceProvider.java
@@ -7,238 +7,169 @@
 import java.net.URI;
 import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
 
 import javax.swing.Icon;
 
-import net.sf.taverna.raven.repository.BasicArtifact;
-import net.sf.taverna.t2.activities.beanshell.BeanshellActivity;
-import net.sf.taverna.t2.activities.localworker.LocalworkerActivity;
-import net.sf.taverna.t2.activities.localworker.LocalworkerActivityConfigurationBean;
 import net.sf.taverna.t2.servicedescriptions.ServiceDescription;
 import net.sf.taverna.t2.servicedescriptions.ServiceDescriptionProvider;
 import net.sf.taverna.t2.workflowmodel.processor.activity.Activity;
-import net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean;
-import net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityOutputPortDefinitionBean;
-import net.sf.taverna.t2.workflowmodel.serialization.xml.ActivityXMLDeserializer;
 
 import org.apache.log4j.Logger;
-import org.jdom.Element;
-import org.jdom.JDOMException;
-import org.jdom.input.SAXBuilder;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
 
 public class LocalworkerServiceProvider implements ServiceDescriptionProvider {
 
 	private static final String LOCALWORKER_NAMES = "/localworker_names";
-	
+
 	private static final String LOCALWORKER_SERVICE = "Local service";
 
 	private static Logger logger = Logger.getLogger(Logger.class);
 
 	private static final URI providerId = URI
-	.create("http://taverna.sf.net/2010/service-provider/localworker");
-	
+			.create("http://taverna.sf.net/2010/service-provider/localworker");
+
 	/** Used to deserialize the Activities stored on disk */
-	private ActivityXMLDeserializer deserializer = ActivityXMLDeserializer.getInstance();;
+	private ObjectMapper objectMapper = new ObjectMapper();
 
 	private static Map<String, String> localWorkerToScript = new HashMap<String, String>();
 
 	static {
-		localWorkerToScript.put(
-				"org.embl.ebi.escience.scuflworkers.java.ByteArrayToString",
+		localWorkerToScript.put("org.embl.ebi.escience.scuflworkers.java.ByteArrayToString",
 				"Byte Array To String");
-		localWorkerToScript.put(
-				"org.embl.ebi.escience.scuflworkers.java.DecodeBase64",
+		localWorkerToScript.put("org.embl.ebi.escience.scuflworkers.java.DecodeBase64",
 				"Decode Base 64 to byte Array");
-		localWorkerToScript.put(
-				"org.embl.ebi.escience.scuflworkers.java.EchoList", "Echo List");
-		localWorkerToScript.put(
-				"org.embl.ebi.escience.scuflworkers.java.EmitLotsOfStrings",
+		localWorkerToScript.put("org.embl.ebi.escience.scuflworkers.java.EchoList", "Echo List");
+		localWorkerToScript.put("org.embl.ebi.escience.scuflworkers.java.EmitLotsOfStrings",
 				"Create Lots Of Strings");
-		localWorkerToScript.put(
-				"org.embl.ebi.escience.scuflworkers.java.EncodeBase64",
+		localWorkerToScript.put("org.embl.ebi.escience.scuflworkers.java.EncodeBase64",
 				"Encode Byte Array to Base 64");
-		localWorkerToScript.put(
-				"org.embl.ebi.escience.scuflworkers.java.ExtractImageLinks",
+		localWorkerToScript.put("org.embl.ebi.escience.scuflworkers.java.ExtractImageLinks",
 				"Get image URLs from HTTP document");
-		localWorkerToScript.put(
-				"org.embl.ebi.escience.scuflworkers.java.FilterStringList",
+		localWorkerToScript.put("org.embl.ebi.escience.scuflworkers.java.FilterStringList",
 				"Filter List of Strings by regex");
-		localWorkerToScript.put(
-				"org.embl.ebi.escience.scuflworkers.java.FlattenList",
+		localWorkerToScript.put("org.embl.ebi.escience.scuflworkers.java.FlattenList",
 				"Flatten List");
-		localWorkerToScript.put(
-				"org.embl.ebi.escience.scuflworkers.java.PadNumber",
+		localWorkerToScript.put("org.embl.ebi.escience.scuflworkers.java.PadNumber",
 				"Pad numeral with leading 0s");
-		localWorkerToScript
-				.put(
-						"org.embl.ebi.escience.scuflworkers.java.RegularExpressionStringList",
-						"Filter list of strings extracting match to a regex");
 		localWorkerToScript.put(
-				"org.embl.ebi.escience.scuflworkers.java.SendEmail",
+				"org.embl.ebi.escience.scuflworkers.java.RegularExpressionStringList",
+				"Filter list of strings extracting match to a regex");
+		localWorkerToScript.put("org.embl.ebi.escience.scuflworkers.java.SendEmail",
 				"Send an Email");
-		localWorkerToScript.put(
-				"org.embl.ebi.escience.scuflworkers.java.SliceList",
+		localWorkerToScript.put("org.embl.ebi.escience.scuflworkers.java.SliceList",
 				"Extract Elements from a List");
-		localWorkerToScript.put(
-				"org.embl.ebi.escience.scuflworkers.java.SplitByRegex",
+		localWorkerToScript.put("org.embl.ebi.escience.scuflworkers.java.SplitByRegex",
 				"Split string into string list by regular expression");
-		localWorkerToScript.put(
-				"org.embl.ebi.escience.scuflworkers.java.StringConcat",
+		localWorkerToScript.put("org.embl.ebi.escience.scuflworkers.java.StringConcat",
 				"Concatenate two strings");
-		localWorkerToScript.put(
-				"org.embl.ebi.escience.scuflworkers.java.StringListMerge",
+		localWorkerToScript.put("org.embl.ebi.escience.scuflworkers.java.StringListMerge",
 				"Merge String List to a String");
-		localWorkerToScript.put(
-				"org.embl.ebi.escience.scuflworkers.java.StringSetDifference",
+		localWorkerToScript.put("org.embl.ebi.escience.scuflworkers.java.StringSetDifference",
 				"String List Difference");
-		localWorkerToScript
-				.put(
-						"org.embl.ebi.escience.scuflworkers.java.StringSetIntersection",
-						"String List Intersection");
-		localWorkerToScript.put(
-				"org.embl.ebi.escience.scuflworkers.java.StringSetUnion",
+		localWorkerToScript.put("org.embl.ebi.escience.scuflworkers.java.StringSetIntersection",
+				"String List Intersection");
+		localWorkerToScript.put("org.embl.ebi.escience.scuflworkers.java.StringSetUnion",
 				"String List Union");
-		localWorkerToScript
-				.put(
-						"org.embl.ebi.escience.scuflworkers.java.StringStripDuplicates",
-						"Remove String Duplicates");
-		localWorkerToScript
-				.put(
-						"org.embl.ebi.escience.scuflworkers.java.TestAlwaysFailingProcessor",
-						"Always Fails");
-		localWorkerToScript
-		.put(
-				"org.embl.ebi.escience.scuflworkers.java.TestSometimesFails",
+		localWorkerToScript.put("org.embl.ebi.escience.scuflworkers.java.StringStripDuplicates",
+				"Remove String Duplicates");
+		localWorkerToScript.put(
+				"org.embl.ebi.escience.scuflworkers.java.TestAlwaysFailingProcessor",
+				"Always Fails");
+		localWorkerToScript.put("org.embl.ebi.escience.scuflworkers.java.TestSometimesFails",
 				"Sometimes Fails");
-		localWorkerToScript.put(
-				"org.embl.ebi.escience.scuflworkers.java.WebImageFetcher",
+		localWorkerToScript.put("org.embl.ebi.escience.scuflworkers.java.WebImageFetcher",
 				"Get Image From URL");
-		localWorkerToScript.put(
-				"org.embl.ebi.escience.scuflworkers.java.WebPageFetcher",
+		localWorkerToScript.put("org.embl.ebi.escience.scuflworkers.java.WebPageFetcher",
 				"Get Web Page from URL");
 
 		// xml:XPathText
-		localWorkerToScript.put(
-				"net.sourceforge.taverna.scuflworkers.xml.XPathTextWorker",
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.xml.XPathTextWorker",
 				"XPath From Text");
-		localWorkerToScript.put(
-				"net.sourceforge.taverna.scuflworkers.xml.XSLTWorker",
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.xml.XSLTWorker",
 				"Transform XML");
+		localWorkerToScript.put(
+				"net.sourceforge.taverna.scuflworkers.xml.XSLTWorkerWithParameters",
+				"Transform XML with parameters");
 
 		// biojava
-		localWorkerToScript
-				.put(
-						"net.sourceforge.taverna.scuflworkers.biojava.GenBankParserWorker",
-						"Read Gen Bank File");
-		localWorkerToScript
-				.put(
-						"net.sourceforge.taverna.scuflworkers.biojava.ReverseCompWorker",
-						"Reverse Complement DNA");
-		localWorkerToScript
-				.put(
-						"net.sourceforge.taverna.scuflworkers.biojava.SwissProtParserWorker",
-						"Read Swiss Prot File");
-		localWorkerToScript
-				.put(
-						"net.sourceforge.taverna.scuflworkers.biojava.TranscribeWorker",
-						"Transcribe DNA");
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.biojava.GenBankParserWorker",
+				"Read Gen Bank File");
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.biojava.ReverseCompWorker",
+				"Reverse Complement DNA");
+		localWorkerToScript.put(
+				"net.sourceforge.taverna.scuflworkers.biojava.SwissProtParserWorker",
+				"Read Swiss Prot File");
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.biojava.TranscribeWorker",
+				"Transcribe DNA");
 
 		// io
-		localWorkerToScript.put(
-				"net.sourceforge.taverna.scuflworkers.io.TextFileReader",
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.io.TextFileReader",
 				"Read Text File");
-		localWorkerToScript.put(
-				"net.sourceforge.taverna.scuflworkers.io.TextFileWriter",
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.io.TextFileWriter",
 				"Write Text File");
-		localWorkerToScript.put(
-				"net.sourceforge.taverna.scuflworkers.io.LocalCommand",
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.io.LocalCommand",
 				"Execute Command Line App");
-		localWorkerToScript.put(
-				"net.sourceforge.taverna.scuflworkers.io.FileListByExtTask",
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.io.FileListByExtTask",
 				"List Files by Extension");
-		localWorkerToScript.put(
-				"net.sourceforge.taverna.scuflworkers.io.FileListByRegexTask",
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.io.FileListByRegexTask",
 				"List Files By Regex");
-		localWorkerToScript.put(
-				"net.sourceforge.taverna.scuflworkers.io.DataRangeTask",
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.io.DataRangeTask",
 				"Select Data Range From File");
-		localWorkerToScript
-				.put(
-						"net.sourceforge.taverna.scuflworkers.io.ConcatenateFileListWorker",
-						"Concatenate Files");
 		localWorkerToScript.put(
-				"net.sourceforge.taverna.scuflworkers.io.EnvVariableWorker",
+				"net.sourceforge.taverna.scuflworkers.io.ConcatenateFileListWorker",
+				"Concatenate Files");
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.io.EnvVariableWorker",
 				"Get Environment Variables as XML");
 
 		// ui
-		localWorkerToScript.put(
-				"net.sourceforge.taverna.scuflworkers.ui.AskWorker",
-				"Ask");
-		localWorkerToScript.put(
-				"net.sourceforge.taverna.scuflworkers.ui.SelectWorker",
-				"Select");
-		localWorkerToScript.put(
-				"net.sourceforge.taverna.scuflworkers.ui.ChooseWorker",
-				"Choose");
-		localWorkerToScript.put(
-				"net.sourceforge.taverna.scuflworkers.ui.TellWorker",
-				"Tell");
-		localWorkerToScript.put(
-				"net.sourceforge.taverna.scuflworkers.ui.WarnWorker",
-				"Warn");
-		localWorkerToScript.put(
-				"net.sourceforge.taverna.scuflworkers.ui.SelectFileWorker",
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.ui.AskWorker", "Ask");
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.ui.SelectWorker", "Select");
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.ui.ChooseWorker", "Choose");
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.ui.TellWorker", "Tell");
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.ui.WarnWorker", "Warn");
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.ui.SelectFileWorker",
 				"Select File");
 		// ncbi
-		localWorkerToScript
-				.put(
-						"net.sourceforge.taverna.scuflworkers.ncbi.NucleotideFastaWorker",
-						"Get Nucleotide FASTA");
-		localWorkerToScript
-				.put(
-						"net.sourceforge.taverna.scuflworkers.ncbi.NucleotideGBSeqWorker",
-						"Get Nucleotide GBSeq XML");
-		localWorkerToScript
-				.put(
-						"net.sourceforge.taverna.scuflworkers.ncbi.NucleotideINSDSeqXMLWorker",
-						"Get Nucleotide INSDSeq XML");
-		localWorkerToScript
-				.put(
-						"net.sourceforge.taverna.scuflworkers.ncbi.NucleotideTinySeqXMLWorker",
-						"Get Nucleotide TinySeq XML");
-
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.ncbi.NucleotideFastaWorker",
+				"Get Nucleotide FASTA");
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.ncbi.NucleotideGBSeqWorker",
+				"Get Nucleotide GBSeq XML");
 		localWorkerToScript.put(
-				"net.sourceforge.taverna.scuflworkers.ncbi.ProteinFastaWorker",
+				"net.sourceforge.taverna.scuflworkers.ncbi.NucleotideINSDSeqXMLWorker",
+				"Get Nucleotide INSDSeq XML");
+		localWorkerToScript.put(
+				"net.sourceforge.taverna.scuflworkers.ncbi.NucleotideTinySeqXMLWorker",
+				"Get Nucleotide TinySeq XML");
+
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.ncbi.ProteinFastaWorker",
 				"Get Protein FASTA");
-		localWorkerToScript
-				.put(
-						"net.sourceforge.taverna.scuflworkers.ncbi.ProteinINSDSeqXMLWorker",
-						"Get Protein INSDSeq XML");
 		localWorkerToScript.put(
-				"net.sourceforge.taverna.scuflworkers.ncbi.ProteinGBSeqWorker",
+				"net.sourceforge.taverna.scuflworkers.ncbi.ProteinINSDSeqXMLWorker",
+				"Get Protein INSDSeq XML");
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.ncbi.ProteinGBSeqWorker",
 				"Get Protein GBSeq XML");
-		localWorkerToScript
-				.put(
-						"net.sourceforge.taverna.scuflworkers.ncbi.ProteinTinySeqXMLWorker",
-						"Get Protein TinySeq XML");
+		localWorkerToScript.put(
+				"net.sourceforge.taverna.scuflworkers.ncbi.ProteinTinySeqXMLWorker",
+				"Get Protein TinySeq XML");
 
-		localWorkerToScript
-				.put(
-						"net.sourceforge.taverna.scuflworkers.ncbi.PubMedESearchWorker",
-						"Search PubMed XML");
-		localWorkerToScript.put(
-				"net.sourceforge.taverna.scuflworkers.ncbi.PubMedEFetchWorker",
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.ncbi.PubMedESearchWorker",
+				"Search PubMed XML");
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.ncbi.PubMedEFetchWorker",
 				"Get PubMed XML By PMID");
-		
-		localWorkerToScript.put(
-				"net.sourceforge.taverna.scuflworkers.jdbc.SQLQueryWorker",
+
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.jdbc.SQLQueryWorker",
 				"Execute SQL Query");
-		localWorkerToScript.put(
-				"net.sourceforge.taverna.scuflworkers.jdbc.SQLUpdateWorker",
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.jdbc.SQLUpdateWorker",
 				"Execute SQL Update");
+
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.net.BrowseUrl",
+				"Open web browser at a URL");
+		localWorkerToScript.put("net.sourceforge.taverna.scuflworkers.net.ExtractHeader",
+				"Extract HTTP Header");
 	}
 
 	public String getName() {
@@ -246,29 +177,26 @@
 	}
 
 	/**
-	 * Use the
-	 * {@link net.sf.taverna.t2.activities.localworker.translator.LocalworkerTranslator}
-	 * to get a {@link Map} of all the local workers. Use the keys in this map
+	 * Use the {@link net.sf.taverna.t2.activities.localworker.translator.LocalworkerTranslator} to
+	 * get a {@link Map} of all the local workers. Use the keys in this map
 	 * to load all the serialized activities from disk by using
 	 * <code> getClass().getResourceAsStream("/" + className) </code> to get
-	 * them and then the {@link ActivityXMLDeserializer} to get the actual
-	 * {@link Activity}. Create the {@link LocalworkerActivityItem} by
+	 * them and then the {@link ActivityXMLDeserializer} to get the actual {@link Activity}. Create
+	 * the {@link LocalworkerActivityItem} by
 	 * populating them with the correct ports and depths. Sets the category to
 	 * match the T1 version so that a query by category will split the local
 	 * workers in to the correct place.
 	 */
 	public void findServiceDescriptionsAsync(FindServiceDescriptionsCallBack callBack) {
 
-		List<ServiceDescription> items = new ArrayList <ServiceDescription>();
-		
-		InputStream inputStream = getClass().getResourceAsStream(
-				LOCALWORKER_NAMES);
+		List<ServiceDescription> items = new ArrayList<ServiceDescription>();
+
+		InputStream inputStream = getClass().getResourceAsStream(LOCALWORKER_NAMES);
 		if (inputStream == null) {
 			logger.error("Could not find resource " + LOCALWORKER_NAMES);
 			return;
 		}
-		BufferedReader inputReader = new BufferedReader(new InputStreamReader(
-				inputStream));
+		BufferedReader inputReader = new BufferedReader(new InputStreamReader(inputStream));
 		String line = "";
 		String category = null;
 		try {
@@ -290,8 +218,7 @@
 				}
 			}
 		} catch (IOException e1) {
-			logger.warn("Could not read local worker definitions from "
-					+ LOCALWORKER_NAMES);
+			logger.warn("Could not read local worker definitions from " + LOCALWORKER_NAMES);
 		}
 		callBack.partialResults(items);
 		callBack.finished();
@@ -299,7 +226,7 @@
 	}
 
 	@SuppressWarnings("serial")
-	private class ItemCreationException extends Exception {
+	public class ItemCreationException extends Exception {
 
 		public ItemCreationException() {
 			super();
@@ -320,97 +247,32 @@
 	}
 
 	/**
-	 * Loads the deserialised local worker from disk and creates a
-	 * {@link LocalworkerActivityItem} with the correct ports and script from it
-	 * 
+	 * Loads the deserialised local worker from disk and creates a {@link LocalworkerActivityItem}
+	 * with the correct ports and script from it
+	 *
 	 * @param line
 	 * @return a LocalWorker with the appropriate Input/Output ports and script
 	 * @throws ItemCreationException
 	 */
-	private LocalworkerServiceDescription createItem(String line)
-			throws ItemCreationException {
-		//String[] split = line.split("[.]");
+	private LocalworkerServiceDescription createItem(String line) throws ItemCreationException {
 		// get the file from disk
-		String resource = "/" + line;
+		String resource = "/" + line + ".json";
 		InputStream resourceAsStream = getClass().getResourceAsStream(resource);
 		if (resourceAsStream == null) {
-			throw new ItemCreationException("Could not find resource "
-					+ resource);
+			throw new ItemCreationException("Could not find resource " + resource);
 		}
 
-		SAXBuilder builder = new SAXBuilder();
-		Element detachRootElement = null;
+		JsonNode json;
 		try {
-			detachRootElement = builder.build(resourceAsStream)
-					.detachRootElement();
-		} catch (JDOMException e) {
-			throw new ItemCreationException("Could not parse resource "
-					+ resource, e);
+			json = objectMapper.readTree(resourceAsStream);
 		} catch (IOException e) {
-			throw new ItemCreationException("Could not read resource "
-					+ resource, e);
+			throw new ItemCreationException("Could not read resource " + resource, e);
 		}
-		LocalworkerActivity activity = null;
-		try {
-			activity = (LocalworkerActivity) deserializer
-					.deserializeActivity(detachRootElement,
-							new HashMap<String, Element>(), getClass()
-									.getClassLoader());
-		} catch (Exception e) {
-			logger.error("Could not create LocalWorkerServiceDescription", e);
-			throw new ItemCreationException(e);
-		}
-		List<ActivityInputPortDefinitionBean> inputPortBeans = new ArrayList<ActivityInputPortDefinitionBean>();
-		LocalworkerActivityConfigurationBean configuration = (LocalworkerActivityConfigurationBean) activity
-				.getConfiguration();
-		
-		// Translate the old dependencies field into artifactDependencies field
-		// The local worker definition xml files still have the old dependencies field
-		LinkedHashSet<BasicArtifact> artifactDependencies = new LinkedHashSet<BasicArtifact>();
-		for (String dep : configuration.getDependencies()){
-			String[] artifactParts = dep.split(":");
-			if (artifactParts.length == 3) {
-				artifactDependencies.add(new BasicArtifact(artifactParts[0], artifactParts[1],
-						artifactParts[2]));
-			}
-		}
-		configuration.setArtifactDependencies(artifactDependencies);
-
-		for (ActivityInputPortDefinitionBean bean : configuration
-				.getInputPortDefinitions()) {
-			bean.setDepth(bean.getDepth());
-			bean.setName(bean.getName());
-			bean.setHandledReferenceSchemes(bean.getHandledReferenceSchemes());
-			bean.setTranslatedElementType(bean.getTranslatedElementType());
-			// bean.setMimeTypes(bean.getMimeTypes());
-			inputPortBeans.add(bean);
-		}
-		List<ActivityOutputPortDefinitionBean> outputPortBeans = new ArrayList<ActivityOutputPortDefinitionBean>();
-		for (ActivityOutputPortDefinitionBean bean : configuration
-				.getOutputPortDefinitions()) {
-			bean.setDepth(bean.getDepth());
-			bean.setGranularDepth(bean.getGranularDepth());
-			bean.setName(bean.getName());
-			bean.setMimeTypes(bean.getMimeTypes());
-			outputPortBeans.add(bean);
-		}
-
-		String script = ((BeanshellActivity) activity).getConfiguration()
-				.getScript();
 
 		LocalworkerServiceDescription item = new LocalworkerServiceDescription();
-		item.setScript(script);
-		item.setOutputPorts(outputPortBeans);
-		item.setInputPorts(inputPortBeans);
+		item.setJson(json);
 		item.setLocalworkerName(line);
-		// name is last part of the class name that was split
-		//String operation = split[split.length - 1];
-		String operationName = localWorkerToScript.get(line);
-		item.setOperation(operationName);
-		item.setDependencies(((BeanshellActivity) activity).getConfiguration()
-				.getDependencies()); // this property is not in use any more
-		item.setArtifactDependencies(configuration.getArtifactDependencies());
-//		item.setOperation(operation);
+		item.setOperation(localWorkerToScript.get(line));
 		return item;
 
 	}
@@ -418,12 +280,12 @@
 	public Icon getIcon() {
 		return LocalworkerActivityIcon.getLocalworkerIcon();
 	}
-	
+
 	@Override
 	public String toString() {
 		return "Local workers provider";
 	}
-	
+
 	public static String getServiceNameFromClassname(String classname) {
 		return (localWorkerToScript.get(classname));
 	}
diff --git a/src/main/java/net/sf/taverna/t2/activities/localworker/views/LocalworkerActivityConfigView.java b/src/main/java/net/sf/taverna/t2/activities/localworker/views/LocalworkerActivityConfigView.java
index 025190f..155c631 100644
--- a/src/main/java/net/sf/taverna/t2/activities/localworker/views/LocalworkerActivityConfigView.java
+++ b/src/main/java/net/sf/taverna/t2/activities/localworker/views/LocalworkerActivityConfigView.java
@@ -1,84 +1,42 @@
 /*******************************************************************************
- * Copyright (C) 2007 The University of Manchester   
- * 
+ * 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 net.sf.taverna.t2.activities.localworker.views;
 
-import net.sf.taverna.t2.activities.beanshell.views.BeanshellConfigView;
-import net.sf.taverna.t2.activities.localworker.LocalworkerActivity;
-import net.sf.taverna.t2.annotation.annotationbeans.HostInstitution;
-import net.sf.taverna.t2.lang.ui.ModelMap;
-import net.sf.taverna.t2.workbench.ModelMapConstants;
-import net.sf.taverna.t2.workbench.activityicons.ActivityIconManager;
-import net.sf.taverna.t2.workbench.edits.EditManager;
-import net.sf.taverna.t2.workflowmodel.Dataflow;
-import net.sf.taverna.t2.workflowmodel.EditException;
-import net.sf.taverna.t2.workflowmodel.EditsRegistry;
-
-import org.apache.log4j.Logger;
-
+import net.sf.taverna.t2.activities.beanshell.views.BeanshellConfigurationPanel;
+import uk.org.taverna.configuration.app.ApplicationConfiguration;
+import uk.org.taverna.scufl2.api.activity.Activity;
 
 @SuppressWarnings("serial")
-public class LocalworkerActivityConfigView extends BeanshellConfigView{
+public class LocalworkerActivityConfigView extends BeanshellConfigurationPanel {
 
-	private static Logger logger = Logger.getLogger(LocalworkerActivityConfigView.class);
-
-	public LocalworkerActivityConfigView(LocalworkerActivity activity) {
-		super(activity);
-		initLocalworker();
+	public LocalworkerActivityConfigView(Activity activity, ApplicationConfiguration applicationConfiguration) {
+		super(activity, applicationConfiguration);
 	}
 
-	private void initLocalworker() {
-	}
-	
-	public void noteConfiguration() {
-		if (isConfigurationChanged()) {
-			super.noteConfiguration();
-			addAnnotation();
+	public boolean isConfigurationChanged() {
+		boolean configurationChanged = super.isConfigurationChanged();
+		if (configurationChanged) {
+			getJson().put("isAltered", true);
 		}
-	}
-	
-	/**
-	 * Annotate the Activity with the name of the Institution or person who
-	 * created the activity. Useful for Localworkers that have been altered by a
-	 * user
-	 */
-	private void addAnnotation() {
-		// FIXME use a more useful name or a different type of annotation, this
-		// is just here as a marker so that
-		// the colour manager works
-		HostInstitution hostInstitutionAnnotation = new HostInstitution();
-		hostInstitutionAnnotation.setText("UserNameHere");
-
-		try {
-			// force the dataflow view to update with the annotation added,
-			// therefore triggering the localworker to be coloured as a
-			// beanshell
-			EditManager.getInstance().doDataflowEdit(
-					(Dataflow) ModelMap.getInstance().getModel(
-							ModelMapConstants.CURRENT_DATAFLOW),
-					EditsRegistry.getEdits().getAddAnnotationChainEdit(
-							activity, hostInstitutionAnnotation));
-			ActivityIconManager.getInstance().resetIcon(activity);
-		} catch (EditException e) {
-			logger.error(e);
-		}
+		return configurationChanged;
 	}
 
 }
diff --git a/src/main/java/net/sf/taverna/t2/activities/localworker/views/LocalworkerActivityContextualView.java b/src/main/java/net/sf/taverna/t2/activities/localworker/views/LocalworkerActivityContextualView.java
index db79cdd..fc09d57 100644
--- a/src/main/java/net/sf/taverna/t2/activities/localworker/views/LocalworkerActivityContextualView.java
+++ b/src/main/java/net/sf/taverna/t2/activities/localworker/views/LocalworkerActivityContextualView.java
@@ -1,19 +1,19 @@
 /*******************************************************************************
- * Copyright (C) 2007 The University of Manchester   
- * 
+ * 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
@@ -24,60 +24,75 @@
 
 import javax.swing.Action;
 
-import net.sf.taverna.t2.activities.beanshell.BeanshellActivityConfigurationBean;
-import net.sf.taverna.t2.activities.localworker.LocalworkerActivity;
-import net.sf.taverna.t2.activities.localworker.LocalworkerActivityConfigurationBean;
 import net.sf.taverna.t2.activities.localworker.actions.LocalworkerActivityConfigurationAction;
 import net.sf.taverna.t2.activities.localworker.servicedescriptions.LocalworkerServiceProvider;
-import net.sf.taverna.t2.annotation.AnnotationAssertion;
-import net.sf.taverna.t2.annotation.AnnotationChain;
-import net.sf.taverna.t2.annotation.annotationbeans.HostInstitution;
+import net.sf.taverna.t2.servicedescriptions.ServiceDescriptionRegistry;
+import net.sf.taverna.t2.workbench.activityicons.ActivityIconManager;
+import net.sf.taverna.t2.workbench.configuration.colour.ColourManager;
+import net.sf.taverna.t2.workbench.edits.EditManager;
+import net.sf.taverna.t2.workbench.file.FileManager;
 import net.sf.taverna.t2.workbench.ui.actions.activity.HTMLBasedActivityContextualView;
-import net.sf.taverna.t2.workflowmodel.processor.activity.Activity;
-import net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean;
-import net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityOutputPortDefinitionBean;
+import uk.org.taverna.configuration.app.ApplicationConfiguration;
+import uk.org.taverna.scufl2.api.activity.Activity;
+import uk.org.taverna.scufl2.api.configurations.Configuration;
+import uk.org.taverna.scufl2.api.port.InputActivityPort;
+import uk.org.taverna.scufl2.api.port.OutputActivityPort;
+
+import com.fasterxml.jackson.databind.JsonNode;
 
 @SuppressWarnings("serial")
-public class LocalworkerActivityContextualView extends
-		HTMLBasedActivityContextualView<LocalworkerActivityConfigurationBean> {
+public class LocalworkerActivityContextualView extends HTMLBasedActivityContextualView {
 
-	public LocalworkerActivityContextualView(Activity<?> activity) {
-		super(activity);
+	private final EditManager editManager;
+	private final FileManager fileManager;
+	private final ActivityIconManager activityIconManager;
+	private final ServiceDescriptionRegistry serviceDescriptionRegistry;
+
+	private final ApplicationConfiguration applicationConfiguration;
+
+	public LocalworkerActivityContextualView(Activity activity, EditManager editManager,
+			FileManager fileManager, ColourManager colourManager,
+			ActivityIconManager activityIconManager,
+			ServiceDescriptionRegistry serviceDescriptionRegistry,
+			ApplicationConfiguration applicationConfiguration) {
+		super(activity, colourManager);
+		this.editManager = editManager;
+		this.fileManager = fileManager;
+		this.activityIconManager = activityIconManager;
+		this.serviceDescriptionRegistry = serviceDescriptionRegistry;
+		this.applicationConfiguration = applicationConfiguration;
 	}
 
 	@Override
 	protected String getRawTableRowsHtml() {
-		String html = "<tr><th>Input Port Name</th><th>Depth</th></tr>";
-		for (ActivityInputPortDefinitionBean bean : getConfigBean()
-				.getInputPortDefinitions()) {
-			html = html + "<tr><td>" + bean.getName() + "</td><td>"
-					+ bean.getDepth() + "</td></tr>";
+		StringBuilder html = new StringBuilder();
+		html.append("<tr><th>Input Port Name</th><th>Depth</th></tr>");
+		for (InputActivityPort inputActivityPort : getActivity().getInputPorts()) {
+			html.append("<tr><td>" + inputActivityPort.getName() + "</td><td>");
+			html.append(inputActivityPort.getDepth() + "</td></tr>");
 		}
-		html = html
-				+ "<tr><th>Output Port Name</th><th>Depth</th></tr>";
-		for (ActivityOutputPortDefinitionBean bean : getConfigBean()
-				.getOutputPortDefinitions()) {
-			html = html + "<tr></td>" + bean.getName() + "</td><td>"
-					+ bean.getDepth() + "</td>" //<td>" + bean.getGranularDepth()
-					//+ "</td>" 
-					+ "</tr>";
+		html.append("<tr><th>Output Port Name</th><th>Depth</th></tr>");
+		for (OutputActivityPort outputActivityPort : getActivity().getOutputPorts()) {
+			html.append("<tr><td>" + outputActivityPort.getName() + "</td><td>");
+			html.append(outputActivityPort.getDepth() + "</td></tr>");
 		}
-		return html;
+		return html.toString();
 	}
 
 	@Override
 	public String getViewTitle() {
 		String result = "";
-		LocalworkerActivity localActivity = (LocalworkerActivity) getActivity();
-		if (localActivity.isAltered()) {
+		Configuration configuration = getConfigBean();
+		JsonNode json = configuration.getJson();
+		String workerName = LocalworkerServiceProvider.getServiceNameFromClassname(json.get(
+				"localworkerName").textValue());
+		if (json.get("isAltered").booleanValue()) {
 			result = "Altered local worker service";
-			String workerName = LocalworkerServiceProvider.getServiceNameFromClassname(localActivity.getConfiguration().getLocalworkerName());
 			if ((workerName != null) && !workerName.equals("")) {
 				result += " - originally " + workerName;
 			}
 		} else {
 			result = "Local worker service";
-			String workerName = LocalworkerServiceProvider.getServiceNameFromClassname(localActivity.getConfiguration().getLocalworkerName());
 			if ((workerName != null) && !workerName.equals("")) {
 				result += " - " + workerName;
 			}
@@ -85,22 +100,11 @@
 		return result;
 	}
 
-	private boolean checkAnnotations() {
-		for (AnnotationChain chain : getActivity().getAnnotations()) {
-			for (AnnotationAssertion<?> assertion : chain.getAssertions()) {
-				Object detail = assertion.getDetail();
-				if (detail instanceof HostInstitution) {
-					return true;
-				}
-			}
-		}
-		return false;
-	}
-
 	@Override
 	public Action getConfigureAction(Frame owner) {
-		return new LocalworkerActivityConfigurationAction(
-				(LocalworkerActivity) getActivity(), owner);
+		return new LocalworkerActivityConfigurationAction(getActivity(), owner, editManager,
+				fileManager, activityIconManager, serviceDescriptionRegistry,
+				applicationConfiguration);
 	}
 
 	@Override
diff --git a/src/main/java/net/sf/taverna/t2/activities/localworker/views/LocalworkerActivityViewFactory.java b/src/main/java/net/sf/taverna/t2/activities/localworker/views/LocalworkerActivityViewFactory.java
index f173776..4fec0a2 100644
--- a/src/main/java/net/sf/taverna/t2/activities/localworker/views/LocalworkerActivityViewFactory.java
+++ b/src/main/java/net/sf/taverna/t2/activities/localworker/views/LocalworkerActivityViewFactory.java
@@ -1,19 +1,19 @@
 /*******************************************************************************
- * Copyright (C) 2007 The University of Manchester   
- * 
+ * 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
@@ -23,19 +23,60 @@
 import java.util.Arrays;
 import java.util.List;
 
-import net.sf.taverna.t2.activities.localworker.LocalworkerActivity;
+import net.sf.taverna.t2.activities.localworker.servicedescriptions.LocalworkerServiceDescription;
+import net.sf.taverna.t2.servicedescriptions.ServiceDescriptionRegistry;
+import net.sf.taverna.t2.workbench.activityicons.ActivityIconManager;
+import net.sf.taverna.t2.workbench.configuration.colour.ColourManager;
+import net.sf.taverna.t2.workbench.edits.EditManager;
+import net.sf.taverna.t2.workbench.file.FileManager;
 import net.sf.taverna.t2.workbench.ui.views.contextualviews.ContextualView;
 import net.sf.taverna.t2.workbench.ui.views.contextualviews.activity.ContextualViewFactory;
+import uk.org.taverna.configuration.app.ApplicationConfiguration;
+import uk.org.taverna.scufl2.api.activity.Activity;
 
-public class LocalworkerActivityViewFactory implements
-		ContextualViewFactory<LocalworkerActivity> {
+public class LocalworkerActivityViewFactory implements ContextualViewFactory<Activity> {
+
+	private EditManager editManager;
+	private FileManager fileManager;
+	private ActivityIconManager activityIconManager;
+	private ColourManager colourManager;
+	private ServiceDescriptionRegistry serviceDescriptionRegistry;
+	private ApplicationConfiguration applicationConfiguration;
 
 	public boolean canHandle(Object object) {
-		return object instanceof LocalworkerActivity;
+		return object instanceof Activity
+				&& ((Activity) object).getType()
+						.equals(LocalworkerServiceDescription.ACTIVITY_TYPE);
 	}
 
-	public List<ContextualView> getViews(LocalworkerActivity activity) {
-		return Arrays.asList(new ContextualView[] {new LocalworkerActivityContextualView(activity)});
+	public List<ContextualView> getViews(Activity activity) {
+		return Arrays.asList(new ContextualView[] { new LocalworkerActivityContextualView(activity,
+				editManager, fileManager, colourManager, activityIconManager,
+				serviceDescriptionRegistry, applicationConfiguration) });
+	}
+
+	public void setEditManager(EditManager editManager) {
+		this.editManager = editManager;
+	}
+
+	public void setFileManager(FileManager fileManager) {
+		this.fileManager = fileManager;
+	}
+
+	public void setActivityIconManager(ActivityIconManager activityIconManager) {
+		this.activityIconManager = activityIconManager;
+	}
+
+	public void setColourManager(ColourManager colourManager) {
+		this.colourManager = colourManager;
+	}
+
+	public void setServiceDescriptionRegistry(ServiceDescriptionRegistry serviceDescriptionRegistry) {
+		this.serviceDescriptionRegistry = serviceDescriptionRegistry;
+	}
+
+	public void setApplicationConfiguration(ApplicationConfiguration applicationConfiguration) {
+		this.applicationConfiguration = applicationConfiguration;
 	}
 
 }
diff --git a/src/main/resources/META-INF/spring/localworker-activity-ui-context-osgi.xml b/src/main/resources/META-INF/spring/localworker-activity-ui-context-osgi.xml
new file mode 100644
index 0000000..dd4c7a8
--- /dev/null
+++ b/src/main/resources/META-INF/spring/localworker-activity-ui-context-osgi.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans:beans xmlns="http://www.springframework.org/schema/osgi" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xmlns:beans="http://www.springframework.org/schema/beans"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans
+                      http://www.springframework.org/schema/beans/spring-beans.xsd
+                      http://www.springframework.org/schema/osgi
+                      http://www.springframework.org/schema/osgi/spring-osgi.xsd">
+
+	<service ref="LocalworkerActivityIcon" interface="net.sf.taverna.t2.workbench.activityicons.ActivityIconSPI" />
+
+	<service ref="LocalworkerServiceProvider" interface="net.sf.taverna.t2.servicedescriptions.ServiceDescriptionProvider" />
+
+	<service ref="ConfigureLocalworkerMenuAction" auto-export="interfaces" />
+
+	<service ref="LocalworkerActivityViewFactory" interface="net.sf.taverna.t2.workbench.ui.views.contextualviews.activity.ContextualViewFactory" />
+
+	<reference id="editManager" interface="net.sf.taverna.t2.workbench.edits.EditManager" />
+	<reference id="fileManager" interface="net.sf.taverna.t2.workbench.file.FileManager" />
+	<reference id="activityIconManager" interface="net.sf.taverna.t2.workbench.activityicons.ActivityIconManager" />
+	<reference id="colourManager" interface="net.sf.taverna.t2.workbench.configuration.colour.ColourManager" />
+	<reference id="serviceDescriptionRegistry" interface="net.sf.taverna.t2.servicedescriptions.ServiceDescriptionRegistry" />
+	<reference id="applicationConfiguration" interface="uk.org.taverna.configuration.app.ApplicationConfiguration" />
+
+</beans:beans>
diff --git a/src/main/resources/META-INF/spring/localworker-activity-ui-context.xml b/src/main/resources/META-INF/spring/localworker-activity-ui-context.xml
new file mode 100644
index 0000000..edcd6be
--- /dev/null
+++ b/src/main/resources/META-INF/spring/localworker-activity-ui-context.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://www.springframework.org/schema/beans
+                      http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+	<bean id="LocalworkerActivityIcon" class="net.sf.taverna.t2.activities.localworker.servicedescriptions.LocalworkerActivityIcon" />
+
+	<bean id="LocalworkerServiceProvider" class="net.sf.taverna.t2.activities.localworker.servicedescriptions.LocalworkerServiceProvider" />
+
+	<bean id="ConfigureLocalworkerMenuAction" class="net.sf.taverna.t2.activities.localworker.menu.ConfigureLocalworkerMenuAction">
+			<property name="editManager" ref="editManager" />
+			<property name="fileManager" ref="fileManager" />
+			<property name="activityIconManager" ref="activityIconManager" />
+			<property name="serviceDescriptionRegistry" ref="serviceDescriptionRegistry" />
+			<property name="applicationConfiguration" ref="applicationConfiguration" />
+	</bean>
+
+	<bean id="LocalworkerActivityViewFactory" class="net.sf.taverna.t2.activities.localworker.views.LocalworkerActivityViewFactory">
+			<property name="editManager" ref="editManager" />
+			<property name="fileManager" ref="fileManager" />
+			<property name="activityIconManager" ref="activityIconManager" />
+			<property name="colourManager" ref="colourManager" />
+			<property name="serviceDescriptionRegistry" ref="serviceDescriptionRegistry" />
+			<property name="applicationConfiguration" ref="applicationConfiguration" />
+	</bean>
+
+</beans>
diff --git a/src/main/resources/localworker_names b/src/main/resources/localworker_names
index fd03268..3df452c 100644
--- a/src/main/resources/localworker_names
+++ b/src/main/resources/localworker_names
@@ -21,6 +21,7 @@
 category:xml
 net.sourceforge.taverna.scuflworkers.xml.XPathTextWorker
 net.sourceforge.taverna.scuflworkers.xml.XSLTWorker
+net.sourceforge.taverna.scuflworkers.xml.XSLTWorkerWithParameters
 category:list
 org.embl.ebi.escience.scuflworkers.java.EchoList
 org.embl.ebi.escience.scuflworkers.java.FlattenList
@@ -45,6 +46,8 @@
 org.embl.ebi.escience.scuflworkers.java.WebPageFetcher
 org.embl.ebi.escience.scuflworkers.java.ExtractImageLinks
 org.embl.ebi.escience.scuflworkers.java.SendEmail
+net.sourceforge.taverna.scuflworkers.net.BrowseUrl
+net.sourceforge.taverna.scuflworkers.net.ExtractHeader
 category:base64
 org.embl.ebi.escience.scuflworkers.java.EncodeBase64
 org.embl.ebi.escience.scuflworkers.java.DecodeBase64
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.GenBankParserWorker b/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.GenBankParserWorker
index 978504b..d6c62b2 100644
--- a/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.GenBankParserWorker
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.GenBankParserWorker
@@ -19,7 +19,11 @@
 		}

 		return new BufferedReader(reader);

 	}

-	

+

+if ((fileUrl == void) || (fileUrl == null)) {

+    throw new RuntimeException("The fileUrl must be specified");

+}

+

 BufferedReader br  = getReader(fileUrl);

 

 // read the GenBank File

@@ -37,7 +41,9 @@
 	sb.append(os.toString());

 }

 

-genbankdata = sb.toString()

+genbankdata = sb.toString();

+br.close();

+ps.close();

   

 </script>

   <dependencies class="java.util.Collections$SingletonList">

diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.GenBankParserWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.GenBankParserWorker.json
new file mode 100644
index 0000000..452850f
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.GenBankParserWorker.json
@@ -0,0 +1,16 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "import org.biojava.bio.seq.Sequence;\nimport org.biojava.bio.seq.SequenceIterator;\nimport org.biojava.bio.seq.io.SeqIOTools;\nimport org.biojava.bio.seq.io.agave.AgaveWriter;\n\nBufferedReader getReader (String fileUrl) throws IOException {\n\t\tInputStreamReader reader;\n\t\ttry {\n\t\t\treader = new FileReader(fileUrl);\n\t\t}\n\t\tcatch (FileNotFoundException e) {\n\t\t\t// try a real URL instead\n\t\t\tURL url = new URL(fileUrl);\n\t\t\treader = new InputStreamReader (url.openStream());\n\t\t}\n\t\treturn new BufferedReader(reader);\n\t}\n\nif ((fileUrl == void) || (fileUrl == null)) {\n    throw new RuntimeException(\"The fileUrl must be specified\");\n}\n\nBufferedReader br  = getReader(fileUrl);\n\n// read the GenBank File\nSequenceIterator sequences = SeqIOTools.readGenbank(br);\n\n// iterate through the sequences\nByteArrayOutputStream os = new ByteArrayOutputStream();\nStringBuffer sb = new StringBuffer();\nAgaveWriter writer = new AgaveWriter();\nPrintStream ps = new PrintStream(os);\n\nwhile (sequences.hasNext()) {\n\tSequence seq = sequences.nextSequence();\n\twriter.writeSequence(seq, ps);\n\tsb.append(os.toString());\n}\n\ngenbankdata = sb.toString();\nbr.close();\nps.close();\n  \n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.biojava.GenBankParserWorker",
+  "inputPorts" : [ {
+    "name" : "fileUrl",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "genbankdata",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.ReverseCompWorker b/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.ReverseCompWorker
index 11855e4..0044c82 100644
--- a/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.ReverseCompWorker
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.ReverseCompWorker
@@ -2,6 +2,10 @@
   <script>import org.biojava.bio.seq.DNATools;

 import org.biojava.bio.symbol.SymbolList;

 

+if ((rawSeq == void) || (rawSeq == null)) {

+    throw new RuntimeException("The rawSeq must be specified");

+}

+

 // make a DNA SymbolListbena

 SymbolList symL = DNATools.createDNA(rawSeq);

 

diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.ReverseCompWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.ReverseCompWorker.json
new file mode 100644
index 0000000..c214819
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.ReverseCompWorker.json
@@ -0,0 +1,16 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "import org.biojava.bio.seq.DNATools;\nimport org.biojava.bio.symbol.SymbolList;\n\nif ((rawSeq == void) || (rawSeq == null)) {\n    throw new RuntimeException(\"The rawSeq must be specified\");\n}\n\n// make a DNA SymbolListbena\nSymbolList symL = DNATools.createDNA(rawSeq);\n\n// reverse complement it\nsymL = DNATools.reverseComplement(symL);\n\n// prove that it worked\nrevSeq = symL.seqString();\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.biojava.ReverseCompWorker",
+  "inputPorts" : [ {
+    "name" : "rawSeq",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "revSeq",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.SwissProtParserWorker b/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.SwissProtParserWorker
index e886280..7f64778 100644
--- a/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.SwissProtParserWorker
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.SwissProtParserWorker
@@ -17,6 +17,10 @@
 		return new BufferedReader(reader);

 	}

 	

+if ((fileUrl == void) || (fileUrl == null)) {

+    throw new RuntimeException("The fileUrl must be specified");

+}

+	

 BufferedReader br = getReader(fileUrl);

 

 // read the EMBL File

@@ -35,6 +39,9 @@
 	sb.append(os.toString());

 }

 results = sb.toString();

+

+br.close();

+ps.close();

   

 </script>

   <dependencies class="java.util.Collections$SingletonList">

diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.SwissProtParserWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.SwissProtParserWorker.json
new file mode 100644
index 0000000..929c316
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.SwissProtParserWorker.json
@@ -0,0 +1,16 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "import org.biojava.bio.seq.Sequence;\nimport org.biojava.bio.seq.SequenceIterator;\nimport org.biojava.bio.seq.io.SeqIOTools;\nimport org.biojava.bio.seq.io.agave.AgaveWriter;\n\nBufferedReader getReader (String fileUrl) throws IOException {\n\t\tInputStreamReader reader;\n\t\ttry {\n\t\t\treader = new FileReader(fileUrl);\n\t\t}\n\t\tcatch (FileNotFoundException e) {\n\t\t\t// try a real URL instead\n\t\t\tURL url = new URL(fileUrl);\n\t\t\treader = new InputStreamReader (url.openStream());\n\t\t}\n\t\treturn new BufferedReader(reader);\n\t}\n\t\nif ((fileUrl == void) || (fileUrl == null)) {\n    throw new RuntimeException(\"The fileUrl must be specified\");\n}\n\t\nBufferedReader br = getReader(fileUrl);\n\n// read the EMBL File\nSequenceIterator sequences = SeqIOTools.readSwissprot(br);\n\n// Prepare the writer\nAgaveWriter writer = new AgaveWriter();\nByteArrayOutputStream os = new ByteArrayOutputStream();\nStringBuffer sb = new StringBuffer();\nPrintStream ps = new PrintStream(os);\n\n// iterate through the sequences\nwhile (sequences.hasNext()) {\n\tSequence seq = sequences.nextSequence();\n\twriter.writeSequence(seq, ps);\n\tsb.append(os.toString());\n}\nresults = sb.toString();\n\nbr.close();\nps.close();\n  \n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.biojava.SwissProtParserWorker",
+  "inputPorts" : [ {
+    "name" : "fileUrl",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "results",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.TranscribeWorker b/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.TranscribeWorker
index c6998af..e46e219 100644
--- a/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.TranscribeWorker
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.TranscribeWorker
@@ -3,6 +3,10 @@
 import org.biojava.bio.seq.RNATools;

 import org.biojava.bio.symbol.SymbolList;

 

+if ((dna_seq == void) || (dna_seq == null)) {

+	throw new RuntimeException("The dna_seq must be specified");

+}

+

 // make a DNA SymbolList

 SymbolList symL = DNATools.createDNA(dna_seq);

 

diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.TranscribeWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.TranscribeWorker.json
new file mode 100644
index 0000000..767852c
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.biojava.TranscribeWorker.json
@@ -0,0 +1,16 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "import org.biojava.bio.seq.DNATools;\nimport org.biojava.bio.seq.RNATools;\nimport org.biojava.bio.symbol.SymbolList;\n\nif ((dna_seq == void) || (dna_seq == null)) {\n\tthrow new RuntimeException(\"The dna_seq must be specified\");\n}\n\n// make a DNA SymbolList\nSymbolList symL = DNATools.createDNA(dna_seq);\n\n// transcribe it to RNA (after BioJava 1.4 this method is\n// deprecated)\nsymL = RNATools.transcribe(symL);\n\n// (after BioJava 1.4 use this method instead)\n// symL = DNATools.toRNA(symL);\n\n// just to prove it worked\nrna_seq = symL.seqString();\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.biojava.TranscribeWorker",
+  "inputPorts" : [ {
+    "name" : "dna_seq",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "rna_seq",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.io.ConcatenateFileListWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.io.ConcatenateFileListWorker.json
new file mode 100644
index 0000000..d91d466
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.io.ConcatenateFileListWorker.json
@@ -0,0 +1,24 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "BufferedReader getReader (String fileUrl) throws IOException {\n\t\tInputStreamReader reader;\n\t\ttry {\n\t\t\treader = new FileReader(fileUrl);\n\t\t}\n\t\tcatch (FileNotFoundException e) {\n\t\t\t// try a real URL instead\n\t\t\tURL url = new URL(fileUrl);\n\t\t\treader = new InputStreamReader (url.openStream());\n\t\t}\n\t\treturn new BufferedReader(reader);\n\t}\n\nString NEWLINE = System.getProperty(\"line.separator\");\n\nboolean displayResults = false;\nif (displayresults != void) {\n\tdisplayResults = Boolean.valueOf(displayresults).booleanValue();\n}\n\nStringBuffer sb = new StringBuffer(2000);\n\nif (outputfile == void) {\n\tthrow new RuntimeException(\"The 'outputfile' parameter cannot be null\");\n}\n\nif (filelist == null) {\n\tthrow new RuntimeException(\"The 'filelist' parameter cannot be null\");\n}\n\nString str = null;\n\nWriter writer = new FileWriter(outputfile);\nfor (int i = 0; i < filelist.size(); i++) {\n\tBufferedReader reader = getReader(filelist.get(i));\n\twhile ((str = reader.readLine()) != null) {\n\t\twriter.write(str);\n\t\twriter.write(NEWLINE);\n\n\t\tif (displayResults) {\n\t\t\tsb.append(str);\n\t\t\tsb.append(NEWLINE);\n\t\t}\n\t}\n\n\treader.close();\n\n}\nwriter.flush();\nwriter.close();\n\nif (displayResults) {\n\tresults= sb.toString();\n}\n\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.io.ConcatenateFileListWorker",
+  "inputPorts" : [ {
+    "name" : "filelist",
+    "depth" : 1,
+    "type" : "String"
+  }, {
+    "name" : "outputfile",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "displayresults",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "results",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.io.EnvVariableWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.io.EnvVariableWorker.json
new file mode 100644
index 0000000..5dc2349
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.io.EnvVariableWorker.json
@@ -0,0 +1,11 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "import java.net.URLEncoder;\n\nProperties sysProps = System.getProperties();\nSet keys = sysProps.keySet();\nIterator it = keys.iterator();\nString currKey = null;\nStringBuffer sb = new StringBuffer();\nsb.append(\"<?xml version=\\\"1.0\\\"?>\\n\");\nsb.append(\"<property-list>\\n\");\nwhile (it.hasNext()) {\n\tcurrKey = (String) it.next();\n\tsb.append(\"<property \");\n\tsb.append(\" name=\\\"\" + URLEncoder.encode(currKey) + \"\\\"\");\n\tsb.append(\" value=\\\"\" + URLEncoder.encode(sysProps.getProperty(currKey)) + \"\\\"/>\\n\");\n}\nsb.append(\"</property-list>\");\n\nproperties = sb.toString();\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.io.EnvVariableWorker",
+  "outputPorts" : [ {
+    "name" : "properties",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.io.FileListByExtTask.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.io.FileListByExtTask.json
new file mode 100644
index 0000000..656453e
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.io.FileListByExtTask.json
@@ -0,0 +1,20 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "class FileExtFilter implements FileFilter {\n\n\tpublic FileExtFilter(String ext) {\n\t\tthis.ext = ext;\n\t}\n\n\tpublic boolean accept(File file) {\n\t\treturn file.getName().endsWith(ext);\n\t}\n\n\tString ext = null;\n}\n\nif (extension == void || extension.equals(\"\")) {\n\tthrow new RuntimeException(\n\t\t\t\"The 'extension' parameter cannot be null.  Please enter a valid file extension.\");\n}\n\nif (directory == void || directory.equals(\"\")) {\n\tthrow new RuntimeException(\n\t\t\t\"The 'directory' parameter cannot be null.  Please enter a valid file directory.\");\n}\n\nFile dirObj = new File(directory);\n\nif (!dirObj.exists()) {\n\tthrow new RuntimeException(\"The 'directory' parameter specified:\" + directory\n\t\t\t+ \"does not exist.  Please enter a valid file directory.\");\n}\n\nFile[] fileObjList = dirObj.listFiles(new FileExtFilter(extension));\nList filelist = new ArrayList();\nfor (int i = 0; i < fileObjList.length; i++) {\n\tfilelist.add(fileObjList[i].getAbsolutePath());\n}\n\n\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.io.FileListByExtTask",
+  "inputPorts" : [ {
+    "name" : "directory",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "extension",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "filelist",
+    "depth" : 1,
+    "granularDepth" : 1
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.io.FileListByRegexTask.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.io.FileListByRegexTask.json
new file mode 100644
index 0000000..35cdb01
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.io.FileListByRegexTask.json
@@ -0,0 +1,20 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "class FileRegexFilter implements FileFilter {\n\n\tpublic FileRegexFilter(String regex) {\n\t\tthis.regex = regex;\n\t}\n\n\tpublic boolean accept(File file) {\n\t\treturn file.getName().matches(regex);\n\t}\n\n\tString regex = null;\n}\n\nif (regex == void || regex.equals(\"\")) {\n\tthrow new RuntimeException(\n\t\t\t\"The 'regex' parameter cannot be null.  Please enter a valid file extension.\");\n}\n\nif (directory == void || directory.equals(\"\")) {\n\tthrow new RuntimeException(\n\t\t\t\"The 'directory' parameter cannot be null.  Please enter a valid file directory.\");\n}\n\nFile dirObj = new File(directory);\n\nif (!dirObj.exists()) {\n\tthrow new RuntimeException(\"The 'directory' parameter specified:\" + directory\n\t\t\t+ \"does not exist.  Please enter a valid file directory.\");\n}\n\nFile[] fileObjList = dirObj.listFiles(new FileRegexFilter(regex));\nList filelist = new ArrayList();\nfor (int i = 0; i < fileObjList.length; i++) {\n\tfilelist.add(fileObjList[i].getAbsolutePath());\n}\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.io.FileListByRegexTask",
+  "inputPorts" : [ {
+    "name" : "directory",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "regex",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "filelist",
+    "depth" : 1,
+    "granularDepth" : 1
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.io.LocalCommand b/src/main/resources/net.sourceforge.taverna.scuflworkers.io.LocalCommand
index 5ca3f94..c0adc09 100644
--- a/src/main/resources/net.sourceforge.taverna.scuflworkers.io.LocalCommand
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.io.LocalCommand
@@ -7,10 +7,8 @@
 

 String osName = System.getProperty("os.name");

 String[] cmdArray = null;

-if (osName.equals("Windows NT") || osName.equals("Windows XP")) {

+if (osName.contains("Windows")) {

 	cmdArray = new String[] { "cmd.exe", "/c", command };

-} else if (osName.equals("Windows 95")) {

-	cmdArray = new String[] { "command.exe", "/c", command };

 } else {// TODO: investigate if this will work in Linux and OSX

 	cmdArray = new String[] { command };

 }

diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.io.LocalCommand.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.io.LocalCommand.json
new file mode 100644
index 0000000..f6ddf4f
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.io.LocalCommand.json
@@ -0,0 +1,20 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "if (command == void || command.equals(\"\")) {\n\tthrow new RuntimeException(\"The 'command' port cannot be null.\");\n}\nProcess proc = null;\nRuntime rt = Runtime.getRuntime();\n\nString osName = System.getProperty(\"os.name\");\nString[] cmdArray = null;\nif (osName.contains(\"Windows\")) {\n\tcmdArray = new String[] { \"cmd.exe\", \"/c\", command };\n} else {// TODO: investigate if this will work in Linux and OSX\n\tcmdArray = new String[] { command };\n}\n\n// concatenate the arrays\nif ((args == void) || (args == null)) {\n\targs = new ArrayList();\n}\n\nint argSize = cmdArray.length + args.size();\nArrayList appArray = new ArrayList(argSize);\nfor (int i = 0; i < cmdArray.length; i++) {\n\tappArray.add(cmdArray[i]);\n}\n\nfor (int i = 0; i < args.size(); i++) {\n\tappArray.add(args.get(i));\n}\n\nString[] applist = new String[argSize];\nappArray.toArray(applist);\nproc = rt.exec(applist);\n\n// Get the input stream and read from it\nInputStream in = proc.getInputStream();\n\nint c;\nStringBuffer sb = new StringBuffer();\nwhile ((c = in.read()) != -1) {\n\tsb.append((char) c);\n}\nin.close();\nresult = sb.toString();\n  \n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.io.LocalCommand",
+  "inputPorts" : [ {
+    "name" : "command",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "args",
+    "depth" : 1,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "result",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.io.TextFileReader b/src/main/resources/net.sourceforge.taverna.scuflworkers.io.TextFileReader
index 767fd3d..6e9adb4 100644
--- a/src/main/resources/net.sourceforge.taverna.scuflworkers.io.TextFileReader
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.io.TextFileReader
@@ -1,13 +1,21 @@
 <activity xmlns="http://taverna.sf.net/2008/xml/t2flow"><class>net.sf.taverna.t2.activities.localworker.LocalworkerActivity</class><inputMap /><outputMap /><configBean encoding="xstream"><net.sf.taverna.t2.activities.localworker.LocalworkerActivityConfigurationBean xmlns="">

-  <script>BufferedReader getReader (String fileUrl) throws IOException {

+  <script>BufferedReader getReader (String fileUrl, String encoding) throws IOException {

 		InputStreamReader reader;

 		try {

-			reader = new FileReader(fileUrl);

+			if (encoding == null) {

+				reader = new FileReader(fileUrl);

+			} else {

+				reader = new InputStreamReader(new FileInputStream(fileUrl),encoding); 

+			}

 		}

 		catch (FileNotFoundException e) {

 			// try a real URL instead

 			URL url = new URL(fileUrl);

-			reader = new InputStreamReader (url.openStream());

+			if (encoding == null) {

+				reader = new InputStreamReader (url.openStream());

+			} else {

+				reader = new InputStreamReader (url.openStream(), encoding);

+			}

 		}

 		return new BufferedReader(reader);

 	}

@@ -16,7 +24,11 @@
 

 StringBuffer sb = new StringBuffer(4000);

 

-BufferedReader in = getReader(fileurl);

+if (encoding == void) {

+	encoding = null;

+}

+

+BufferedReader in = getReader(fileurl, encoding);

 String str;

 String lineEnding = System.getProperty("line.separator");

 

@@ -40,6 +52,16 @@
         <string>'text/plain'</string>

       </mimeTypes>

     </net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean>

+    <net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean>

+      <handledReferenceSchemes />

+      <translatedElementType>java.lang.String</translatedElementType>

+      <allowsLiteralValues>true</allowsLiteralValues>

+      <name>encoding</name>

+      <depth>0</depth>

+      <mimeTypes>

+        <string>'text/plain'</string>

+      </mimeTypes>

+    </net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean>

   </inputs>

   <outputs>

     <net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityOutputPortDefinitionBean>

diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.io.TextFileReader.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.io.TextFileReader.json
new file mode 100644
index 0000000..1424433
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.io.TextFileReader.json
@@ -0,0 +1,20 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "BufferedReader getReader (String fileUrl, String encoding) throws IOException {\n\t\tInputStreamReader reader;\n\t\ttry {\n\t\t\tif (encoding == null) {\n\t\t\t\treader = new FileReader(fileUrl);\n\t\t\t} else {\n\t\t\t\treader = new InputStreamReader(new FileInputStream(fileUrl),encoding); \n\t\t\t}\n\t\t}\n\t\tcatch (FileNotFoundException e) {\n\t\t\t// try a real URL instead\n\t\t\tURL url = new URL(fileUrl);\n\t\t\tif (encoding == null) {\n\t\t\t\treader = new InputStreamReader (url.openStream());\n\t\t\t} else {\n\t\t\t\treader = new InputStreamReader (url.openStream(), encoding);\n\t\t\t}\n\t\t}\n\t\treturn new BufferedReader(reader);\n\t}\n\n\n\nStringBuffer sb = new StringBuffer(4000);\n\nif (encoding == void) {\n\tencoding = null;\n}\n\nBufferedReader in = getReader(fileurl, encoding);\nString str;\nString lineEnding = System.getProperty(\"line.separator\");\n\nwhile ((str = in.readLine()) != null) {\n\tsb.append(str);\n\tsb.append(lineEnding);\n}\nin.close();\nfilecontents = sb.toString();\n  \n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.io.TextFileReader",
+  "inputPorts" : [ {
+    "name" : "fileurl",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "encoding",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "filecontents",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.io.TextFileWriter b/src/main/resources/net.sourceforge.taverna.scuflworkers.io.TextFileWriter
index 6d46180..88ac962 100644
--- a/src/main/resources/net.sourceforge.taverna.scuflworkers.io.TextFileWriter
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.io.TextFileWriter
@@ -1,6 +1,14 @@
 <activity xmlns="http://taverna.sf.net/2008/xml/t2flow"><class>net.sf.taverna.t2.activities.localworker.LocalworkerActivity</class><inputMap /><outputMap /><configBean encoding="xstream"><net.sf.taverna.t2.activities.localworker.LocalworkerActivityConfigurationBean xmlns="">

-  <script>BufferedWriter out = new BufferedWriter(new FileWriter(outputFile));

+  <script>

+  BufferedWriter out;

+  if (encoding == void) {

+  	out = new BufferedWriter(new FileWriter(outputFile));

+  }

+  else {

+  	out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFile), encoding)); 

+  }

 out.write(filecontents);

+out.flush();

 out.close();

 outputFile = filecontents;

 </script>

@@ -26,7 +34,16 @@
         <string>'text/plain'</string>

       </mimeTypes>

     </net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean>

-  </inputs>

+    <net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean>

+      <handledReferenceSchemes />

+      <translatedElementType>java.lang.String</translatedElementType>

+      <allowsLiteralValues>true</allowsLiteralValues>

+      <name>encoding</name>

+      <depth>0</depth>

+      <mimeTypes>

+        <string>'text/plain'</string>

+      </mimeTypes>

+    </net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean>  </inputs>

   <outputs>

     <net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityOutputPortDefinitionBean>

       <granularDepth>0</granularDepth>

diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.io.TextFileWriter.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.io.TextFileWriter.json
new file mode 100644
index 0000000..5a9f368
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.io.TextFileWriter.json
@@ -0,0 +1,24 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "\n  BufferedWriter out;\n  if (encoding == void) {\n  \tout = new BufferedWriter(new FileWriter(outputFile));\n  }\n  else {\n  \tout = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputFile), encoding)); \n  }\nout.write(filecontents);\nout.flush();\nout.close();\noutputFile = filecontents;\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.io.TextFileWriter",
+  "inputPorts" : [ {
+    "name" : "outputFile",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "filecontents",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "encoding",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "outputFile",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.jdbc.SQLQueryWorker b/src/main/resources/net.sourceforge.taverna.scuflworkers.jdbc.SQLQueryWorker
index 1af0c9d..b6263cf 100644
--- a/src/main/resources/net.sourceforge.taverna.scuflworkers.jdbc.SQLQueryWorker
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.jdbc.SQLQueryWorker
@@ -7,6 +7,7 @@
 import java.sql.PreparedStatement;
 import java.sql.ResultSet;
 import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
 
 import javax.sql.rowset.WebRowSet;
 
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.jdbc.SQLQueryWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.jdbc.SQLQueryWorker.json
new file mode 100644
index 0000000..da1f005
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.jdbc.SQLQueryWorker.json
@@ -0,0 +1,44 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "\n import java.sql.Driver;\nimport java.sql.DriverManager;\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\nimport java.sql.ResultSet;\nimport java.sql.ResultSetMetaData;\nimport java.sql.SQLException;\n\nimport javax.sql.rowset.WebRowSet;\n\nimport com.sun.rowset.WebRowSetImpl;\n\n\n\nif ((driver == void) || (driver == null) || driver.equals(\"\")) {\n\tthrow new RuntimeException(\"The driver must be specified\");\n}\n\nif ((url == void) || (url == null) || url.equals(\"\")) {\n\tthrow new RuntimeException(\"The url must be specified\");\n}\n\nboolean provideXmlBoolean = ((provideXml != void) && (provideXml != null) && Boolean.valueOf(provideXml));\n\nif ((params == void) || (params == null)) {\n   params = new ArrayList();\n}\n\nif ((sql == void) || (sql == null) || sql.equals(\"\")) {\n\tthrow new RuntimeException(\"The sql must be specified\");\n}\n\nClass c = Thread.currentThread().getContextClassLoader().loadClass(driver);\n\nif (c == null) {\n\tthrow new RuntimeException(\"Class \" + driver + \" not found\");\n}\n\nDriver d = c.newInstance();\nif (d == null) {\n\tthrow new RuntimeException(\"Could not create instance of driver\");\n}\n\nProperties p = new Properties();\n\nif ((userid == void) || (userid == null)) {\n\tuserid = \"\";\n}\n\np.setProperty(\"user\", userid);\n\nif ((password == void) || (password == null)) {\n\tpassword = \"\";\n}\n\np.setProperty(\"password\", password);\n\nConnection con = null;\nPreparedStatement ps = null;\nResultSet rs = null;\ntry {\n\n\tcon = d.connect(url, p);\n\tps = con.prepareStatement(sql);\n\n\tint paramSize = params.size();\n\tfor (int i = 0; i < paramSize; i++) {\n\t\tps.setObject(i + 1, params.get(i));\n\t}\n\n\trs = ps.executeQuery();\n\n\tif (provideXmlBoolean) {\n\t\tWebRowSet webrs = new WebRowSetImpl();\n\t\tStringWriter sw = new StringWriter();\n\t\twebrs.writeXml(rs, sw);\n\t\txmlresults = sw.toString();\n\t} else {\n\t\txmlresults = \"\";\n\t}\n\n\ttry {\n\t\trs.beforeFirst();\n\t} catch (SQLException e) {\n\t\t// redo the query\n\t\trs = ps.executeQuery();\n\t}\n\n\tResultSetMetaData rsmd = rs.getMetaData();\n\tint numCols = rsmd.getColumnCount();\n\tresultList = new ArrayList();\n\t\n\t// put the results into the results list.\n\twhile (rs.next()) {\n\t\tList row = new ArrayList(numCols);\n\t\tfor (int i = 0; i < numCols; i++) {\n\t\t\tString str = rs.getString(i + 1); \n\t\t\trow.add(str == null ? \"null\" : str); \n\t\t}\n\t\tresultList.add(row);\n\t}\n}\nfinally {\n\tif (rs != null) {\n\t\trs.close();\n\t}\n\tif (ps != null) {\n\t\tps.close();\n\t}\n\tif (con != null) {\n\t\tcon.close();\n\t}\n}\n  \n\n ",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.jdbc.SQLQueryWorker",
+  "inputPorts" : [ {
+    "name" : "driver",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "password",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "userid",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "url",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "provideXml",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "sql",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "params",
+    "depth" : 1,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "resultList",
+    "depth" : 2,
+    "granularDepth" : 2
+  }, {
+    "name" : "xmlresults",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.jdbc.SQLUpdateWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.jdbc.SQLUpdateWorker.json
new file mode 100644
index 0000000..3144afd
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.jdbc.SQLUpdateWorker.json
@@ -0,0 +1,36 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "import java.sql.Driver;\nimport java.sql.DriverManager;\nimport java.sql.Connection;\nimport java.sql.PreparedStatement;\n\nif ((driver == void) || (driver == null) || driver.equals(\"\")) {\n\tthrow new RuntimeException(\"The driver must be specified\");\n}\n\nif ((url == void) || (url == null) || url.equals(\"\")) {\n\tthrow new RuntimeException(\"The url must be specified\");\n}\n\nif ((params == void) || (params == null)) {\n   params = new ArrayList();\n}\n\nif ((sql == void) || (sql == null) || sql.equals(\"\")) {\n\tthrow new RuntimeException(\"The sql must be specified\");\n}\n\nClass c = Thread.currentThread().getContextClassLoader().loadClass(driver);\n\nif (c == null) {\n\tthrow new RuntimeException(\"Class \" + driver + \" not found\");\n}\n\nDriver d = c.newInstance();\nif (d == null) {\n\tthrow new RuntimeException(\"Could not create instance of driver\");\n}\n\nProperties p = new Properties();\n\nif ((userid == void) || (userid == null)) {\n\tuserid = \"\";\n}\n\np.setProperty(\"user\", userid);\n\nif ((password == void) || (password == null)) {\n\tpassword = \"\";\n}\n\np.setProperty(\"password\", password);\n\nConnection con = null;\nPreparedStatement ps = null;\n\ntry {\n\tcon = d.connect(url, p);\n\tps = con.prepareStatement(sql);\n\n\tint paramsSize = params.size();\n\tfor (int i = 0; i < paramsSize; i++) {\n\t\tps.setObject(i + 1, params.get(i));\n\t}\n\n\tps.executeUpdate();\n\n\tresultList = \"update successful\";\n}\nfinally {\n\tif (ps != null) {\n\t\tps.close();\n\t}\n\tif (con != null) {\n\t\tcon.close();\n\t}\n}\n\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.jdbc.SQLUpdateWorker",
+  "inputPorts" : [ {
+    "name" : "driver",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "password",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "userid",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "url",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "sql",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "params",
+    "depth" : 1,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "resultList",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideFastaWorker b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideFastaWorker
index 8ff169f..8b7a680 100644
--- a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideFastaWorker
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideFastaWorker
@@ -16,6 +16,7 @@
         }

         writer.write(buffer, 0, r);

     }

+reader.close();

 outputText = writer.toString();

 </script>

   <dependencies />

diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideFastaWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideFastaWorker.json
new file mode 100644
index 0000000..feb26cc
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideFastaWorker.json
@@ -0,0 +1,16 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "if ((id == void) || (id == null) || id.equals(\"\")) {\n\tthrow new RunTimeException(\"port id must have a non-empty value\");\n}\n\nURL url = new URL (\"http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?rettype=fasta&db=nucleotide&retmode=text&id=\" + id);\n\nBufferedReader reader = new BufferedReader (new InputStreamReader(url.openStream()));\nStringWriter writer = new StringWriter();\n\nchar[] buffer = new char[1024];\n    while (true) {\n        int r = reader.read(buffer);\n        if (r <= 0) {\n            break;\n        }\n        writer.write(buffer, 0, r);\n    }\nreader.close();\noutputText = writer.toString();\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.ncbi.NucleotideFastaWorker",
+  "inputPorts" : [ {
+    "name" : "id",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "outputText",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideGBSeqWorker b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideGBSeqWorker
index 3d054b6..80f791a 100644
--- a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideGBSeqWorker
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideGBSeqWorker
@@ -16,6 +16,7 @@
         }

         writer.write(buffer, 0, r);

     }

+reader.close();

 outputText = writer.toString();

 </script>

   <dependencies />

diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideGBSeqWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideGBSeqWorker.json
new file mode 100644
index 0000000..e616f51
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideGBSeqWorker.json
@@ -0,0 +1,16 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "if ((id == void) || (id == null) || id.equals(\"\")) {\n\tthrow new RunTimeException(\"port id must have a non-empty value\");\n}\n\nURL url = new URL (\"http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?rettype=gb&db=nucleotide&retmode=xml&id=\" + id);\n\nBufferedReader reader = new BufferedReader (new InputStreamReader(url.openStream()));\nStringWriter writer = new StringWriter();\n\nchar[] buffer = new char[1024];\n    while (true) {\n        int r = reader.read(buffer);\n        if (r <= 0) {\n            break;\n        }\n        writer.write(buffer, 0, r);\n    }\nreader.close();\noutputText = writer.toString();\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.ncbi.NucleotideGBSeqWorker",
+  "inputPorts" : [ {
+    "name" : "id",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "outputText",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideINSDSeqXMLWorker b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideINSDSeqXMLWorker
index 900e346..2ce601b 100644
--- a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideINSDSeqXMLWorker
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideINSDSeqXMLWorker
@@ -16,6 +16,7 @@
         }

         writer.write(buffer, 0, r);

     }

+reader.close();

 outputText = writer.toString();

 </script>

   <dependencies />

diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideINSDSeqXMLWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideINSDSeqXMLWorker.json
new file mode 100644
index 0000000..8dfbdbe
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideINSDSeqXMLWorker.json
@@ -0,0 +1,16 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "if ((id == void) || (id == null) || id.equals(\"\")) {\n\tthrow new RunTimeException(\"port id must have a non-empty value\");\n}\n\nURL url = new URL (\"http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?rettype=gbc&db=nucleotide&retmode=xml&id=\" + id);\n\nBufferedReader reader = new BufferedReader (new InputStreamReader(url.openStream()));\nStringWriter writer = new StringWriter();\n\nchar[] buffer = new char[1024];\n    while (true) {\n        int r = reader.read(buffer);\n        if (r <= 0) {\n            break;\n        }\n        writer.write(buffer, 0, r);\n    }\nreader.close();\noutputText = writer.toString();\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.ncbi.NucleotideINSDSeqXMLWorker",
+  "inputPorts" : [ {
+    "name" : "id",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "outputText",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideTinySeqXMLWorker b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideTinySeqXMLWorker
index 7d0bce6..aad694a 100644
--- a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideTinySeqXMLWorker
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideTinySeqXMLWorker
@@ -16,6 +16,7 @@
         }

         writer.write(buffer, 0, r);

     }

+reader.close();

 outputText = writer.toString();

 </script>

   <dependencies />

diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideTinySeqXMLWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideTinySeqXMLWorker.json
new file mode 100644
index 0000000..3867455
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.NucleotideTinySeqXMLWorker.json
@@ -0,0 +1,16 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "if ((id == void) || (id == null) || id.equals(\"\")) {\n\tthrow new RunTimeException(\"port id must have a non-empty value\");\n}\n\nURL url = new URL (\"http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?rettype=fasta&db=nucleotide&retmode=xml&id=\" + id);\n\nBufferedReader reader = new BufferedReader (new InputStreamReader(url.openStream()));\nStringWriter writer = new StringWriter();\n\nchar[] buffer = new char[1024];\n    while (true) {\n        int r = reader.read(buffer);\n        if (r <= 0) {\n            break;\n        }\n        writer.write(buffer, 0, r);\n    }\nreader.close();\noutputText = writer.toString();\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.ncbi.NucleotideTinySeqXMLWorker",
+  "inputPorts" : [ {
+    "name" : "id",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "outputText",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinFastaWorker b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinFastaWorker
index 16236ff..c07b04e 100644
--- a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinFastaWorker
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinFastaWorker
@@ -16,6 +16,7 @@
         }

         writer.write(buffer, 0, r);

     }

+reader.close();

 outputText = writer.toString();

 </script>

   <dependencies />

diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinFastaWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinFastaWorker.json
new file mode 100644
index 0000000..fc5b181
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinFastaWorker.json
@@ -0,0 +1,16 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "if ((id == void) || (id == null) || id.equals(\"\")) {\n\tthrow new RunTimeException(\"port id must have a non-empty value\");\n}\n\nURL url = new URL (\"http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?rettype=fasta&db=protein&retmode=text&id=\" + id);\n\nBufferedReader reader = new BufferedReader (new InputStreamReader(url.openStream()));\nStringWriter writer = new StringWriter();\n\nchar[] buffer = new char[1024];\n    while (true) {\n        int r = reader.read(buffer);\n        if (r <= 0) {\n            break;\n        }\n        writer.write(buffer, 0, r);\n    }\nreader.close();\noutputText = writer.toString();\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.ncbi.ProteinFastaWorker",
+  "inputPorts" : [ {
+    "name" : "id",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "outputText",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinGBSeqWorker b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinGBSeqWorker
index 901b26c..bf85c2b 100644
--- a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinGBSeqWorker
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinGBSeqWorker
@@ -16,6 +16,7 @@
         }

         writer.write(buffer, 0, r);

     }

+reader.close();

 outputText = writer.toString();

 </script>

   <dependencies />

diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinGBSeqWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinGBSeqWorker.json
new file mode 100644
index 0000000..160ce92
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinGBSeqWorker.json
@@ -0,0 +1,16 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "if ((id == void) || (id == null) || id.equals(\"\")) {\n\tthrow new RunTimeException(\"port id must have a non-empty value\");\n}\n\nURL url = new URL (\"http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?rettype=gb&db=protein&retmode=xml&id=\" + id);\n\nBufferedReader reader = new BufferedReader (new InputStreamReader(url.openStream()));\nStringWriter writer = new StringWriter();\n\nchar[] buffer = new char[1024];\n    while (true) {\n        int r = reader.read(buffer);\n        if (r <= 0) {\n            break;\n        }\n        writer.write(buffer, 0, r);\n    }\nreader.close();\noutputText = writer.toString();\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.ncbi.ProteinGBSeqWorker",
+  "inputPorts" : [ {
+    "name" : "id",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "outputText",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinINSDSeqXMLWorker b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinINSDSeqXMLWorker
index 43f04fc..c82209f 100644
--- a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinINSDSeqXMLWorker
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinINSDSeqXMLWorker
@@ -16,6 +16,7 @@
         }

         writer.write(buffer, 0, r);

     }

+reader.close();

 outputText = writer.toString();

 </script>

   <dependencies />

diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinINSDSeqXMLWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinINSDSeqXMLWorker.json
new file mode 100644
index 0000000..6e36120
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinINSDSeqXMLWorker.json
@@ -0,0 +1,16 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "if ((id == void) || (id == null) || id.equals(\"\")) {\n\tthrow new RunTimeException(\"port id must have a non-empty value\");\n}\n\nURL url = new URL (\"http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?rettype=gbc&db=protein&retmode=xml&id=\" + id);\n\nBufferedReader reader = new BufferedReader (new InputStreamReader(url.openStream()));\nStringWriter writer = new StringWriter();\n\nchar[] buffer = new char[1024];\n    while (true) {\n        int r = reader.read(buffer);\n        if (r <= 0) {\n            break;\n        }\n        writer.write(buffer, 0, r);\n    }\nreader.close();\noutputText = writer.toString();\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.ncbi.ProteinINSDSeqXMLWorker",
+  "inputPorts" : [ {
+    "name" : "id",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "outputText",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinTinySeqXMLWorker b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinTinySeqXMLWorker
index 65b5aec..b6f9337 100644
--- a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinTinySeqXMLWorker
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinTinySeqXMLWorker
@@ -16,6 +16,7 @@
         }

         writer.write(buffer, 0, r);

     }

+reader.close();

 outputText = writer.toString();

 </script>

   <dependencies />

diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinTinySeqXMLWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinTinySeqXMLWorker.json
new file mode 100644
index 0000000..471e000
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.ProteinTinySeqXMLWorker.json
@@ -0,0 +1,16 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "if ((id == void) || (id == null) || id.equals(\"\")) {\n\tthrow new RunTimeException(\"port id must have a non-empty value\");\n}\n\nURL url = new URL (\"http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?rettype=fasta&db=protein&retmode=xml&id=\" + id);\n\nBufferedReader reader = new BufferedReader (new InputStreamReader(url.openStream()));\nStringWriter writer = new StringWriter();\n\nchar[] buffer = new char[1024];\n    while (true) {\n        int r = reader.read(buffer);\n        if (r <= 0) {\n            break;\n        }\n        writer.write(buffer, 0, r);\n    }\nreader.close();\noutputText = writer.toString();\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.ncbi.ProteinTinySeqXMLWorker",
+  "inputPorts" : [ {
+    "name" : "id",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "outputText",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.PubMedEFetchWorker b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.PubMedEFetchWorker
index 3ff4024..71fef3c 100644
--- a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.PubMedEFetchWorker
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.PubMedEFetchWorker
@@ -19,6 +19,7 @@
         }

         writer.write(buffer, 0, r);

     }

+reader.close();

 outputText = writer.toString();

 </script>

   <dependencies />

diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.PubMedEFetchWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.PubMedEFetchWorker.json
new file mode 100644
index 0000000..5e2a7df
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.PubMedEFetchWorker.json
@@ -0,0 +1,24 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "if ((id == void) || (id == null) || id.equals(\"\")) {\n\tthrow new RunTimeException(\"port id must have a non-empty value\");\n}\n\nURL url = new URL (\"http://eutils.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?db=pubmed\" +\n\"&rettype=\" + (((rettype == void ) || (rettype == null)) ? \"full\" : rettype) +\n\"&retmode=\" + (((retmode == void) || (retmode == null)) ? \"xml\" : retmode) +\n\"&id=\" + id);\n\nBufferedReader reader = new BufferedReader (new InputStreamReader(url.openStream()));\nStringWriter writer = new StringWriter();\n\nchar[] buffer = new char[1024];\n    while (true) {\n        int r = reader.read(buffer);\n        if (r <= 0) {\n            break;\n        }\n        writer.write(buffer, 0, r);\n    }\nreader.close();\noutputText = writer.toString();\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.ncbi.PubMedEFetchWorker",
+  "inputPorts" : [ {
+    "name" : "id",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "rettype",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "retmode",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "outputText",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.PubMedESearchWorker b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.PubMedESearchWorker
index 4cf502c..37c440c 100644
--- a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.PubMedESearchWorker
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.PubMedESearchWorker
@@ -25,6 +25,7 @@
         }

         writer.write(buffer, 0, r);

     }

+reader.close();

 outputText = writer.toString();

 </script>

   <dependencies />

diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.PubMedESearchWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.PubMedESearchWorker.json
new file mode 100644
index 0000000..bd29f82
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ncbi.PubMedESearchWorker.json
@@ -0,0 +1,44 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "if ((term == void) || (term == null) || term.equals(\"\")) {\n\tthrow new RunTimeException(\"port term must have a non-empty value\");\n}\n\nURL url = new URL (\"http://eutils.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?db=pubmed\" +\n(field == void ? \"\" : (\"&field=\" + field)) +\n(retstart == void ? \"\" : (\"&retstart=\" + retstart)) +\n(retmax == void ? \"\" : (\"&retmax=\" + retmax)) +\n(mindate == void ? \"\" : (\"&mindate=\" + mindate)) +\n(maxdate == void ? \"\" : (\"&maxdate=\" + maxdate)) +\n\"&rettype=\" + (rettype == void ? \"full\" : rettype) +\n\"&retmode=\" + (retmode == void ? \"xml\" : retmode) +\n\"&tool=taverna\" +\n\"&term=\" + term);\n\nBufferedReader reader = new BufferedReader (new InputStreamReader(url.openStream()));\nStringWriter writer = new StringWriter();\n\nchar[] buffer = new char[1024];\n    while (true) {\n        int r = reader.read(buffer);\n        if (r <= 0) {\n            break;\n        }\n        writer.write(buffer, 0, r);\n    }\nreader.close();\noutputText = writer.toString();\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.ncbi.PubMedESearchWorker",
+  "inputPorts" : [ {
+    "name" : "term",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "db",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "field",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "retstart",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "retmax",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "mindate",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "maxdate",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "rettype",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "outputText",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.net.BrowseUrl b/src/main/resources/net.sourceforge.taverna.scuflworkers.net.BrowseUrl
new file mode 100644
index 0000000..a2317c5
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.net.BrowseUrl
@@ -0,0 +1,31 @@
+<activity xmlns="http://taverna.sf.net/2008/xml/t2flow"><class>net.sf.taverna.t2.activities.localworker.LocalworkerActivity</class><inputMap /><outputMap /><configBean encoding="xstream"><net.sf.taverna.t2.activities.localworker.LocalworkerActivityConfigurationBean xmlns="">

+  <inputs>

+    <net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean>

+      <name>url</name>

+      <depth>0</depth>

+      <mimeTypes>

+        <string>text/plain</string>

+      </mimeTypes>

+      <handledReferenceSchemes />

+      <translatedElementType>java.lang.String</translatedElementType>

+      <allowsLiteralValues>true</allowsLiteralValues>

+    </net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean>

+  </inputs>

+  <outputs />

+  <classLoaderSharing>workflow</classLoaderSharing>

+  <localDependencies />

+  <artifactDependencies />

+  <script>import java.awt.Desktop;

+import java.net.URI;

+

+if ((url == void) || (url == null)) {

+	throw new RuntimeException("Url must be specified");

+}

+

+URI uri = null;

+

+uri = new URI(url);

+

+Desktop.getDesktop().browse(uri);</script>

+  <dependencies />

+</net.sf.taverna.t2.activities.localworker.LocalworkerActivityConfigurationBean></configBean><annotations /></activity>
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.net.BrowseUrl.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.net.BrowseUrl.json
new file mode 100644
index 0000000..1a2155e
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.net.BrowseUrl.json
@@ -0,0 +1,11 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "import java.awt.Desktop;\nimport java.net.URI;\n\nif ((url == void) || (url == null)) {\n\tthrow new RuntimeException(\"Url must be specified\");\n}\n\nURI uri = null;\n\nuri = new URI(url);\n\nDesktop.getDesktop().browse(uri);",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.net.BrowseUrl",
+  "inputPorts" : [ {
+    "name" : "url",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.net.ExtractHeader b/src/main/resources/net.sourceforge.taverna.scuflworkers.net.ExtractHeader
new file mode 100644
index 0000000..d3149d6
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.net.ExtractHeader
@@ -0,0 +1,55 @@
+<activity xmlns="http://taverna.sf.net/2008/xml/t2flow"><class>net.sf.taverna.t2.activities.localworker.LocalworkerActivity</class><inputMap /><outputMap /><configBean encoding="xstream"><net.sf.taverna.t2.activities.localworker.LocalworkerActivityConfigurationBean xmlns="">
+  <inputs>
+    <net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean>
+      <name>headers</name>
+      <depth>1</depth>
+      <mimeTypes>
+        <string>text/plain</string>
+      </mimeTypes>
+      <handledReferenceSchemes />
+      <translatedElementType>java.lang.String</translatedElementType>
+      <allowsLiteralValues>true</allowsLiteralValues>
+    </net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean>
+    <net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean>
+      <name>header_key</name>
+      <depth>0</depth>
+      <mimeTypes>
+        <string>text/plain</string>
+      </mimeTypes>
+      <handledReferenceSchemes />
+      <translatedElementType>java.lang.String</translatedElementType>
+      <allowsLiteralValues>true</allowsLiteralValues>
+    </net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean>
+  </inputs>
+  <outputs>
+    <net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityOutputPortDefinitionBean>
+      <name>header_value</name>
+      <depth>0</depth>
+      <mimeTypes />
+      <granularDepth>0</granularDepth>
+    </net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityOutputPortDefinitionBean>
+  </outputs>
+  <classLoaderSharing>workflow</classLoaderSharing>
+  <localDependencies />
+  <artifactDependencies />
+  <script>if ((headers == void) || (headers == null)) {
+	throw new RuntimeException("Headers must be specified");
+}
+
+if ((header_key == void) || (header_key == null)) {
+	throw new RuntimeException("Header_key must be specified");
+}
+
+String header_value = "";
+if (!header_key.endsWith(":")) {
+	header_key += ":";
+}
+for (String h : headers) {
+	if (h.startsWith(header_key)) {
+		header_value = h.substring(header_key.length());
+		header_value = header_value.trim();
+		break;
+	}
+}</script>
+  <dependencies />
+</net.sf.taverna.t2.activities.localworker.LocalworkerActivityConfigurationBean></configBean><annotations /></activity>
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.net.ExtractHeader.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.net.ExtractHeader.json
new file mode 100644
index 0000000..0e510fa
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.net.ExtractHeader.json
@@ -0,0 +1,20 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "if ((headers == void) || (headers == null)) {\n\tthrow new RuntimeException(\"Headers must be specified\");\n}\n\nif ((header_key == void) || (header_key == null)) {\n\tthrow new RuntimeException(\"Header_key must be specified\");\n}\n\nString header_value = \"\";\nif (!header_key.endsWith(\":\")) {\n\theader_key += \":\";\n}\nfor (String h : headers) {\n\tif (h.startsWith(header_key)) {\n\t\theader_value = h.substring(header_key.length());\n\t\theader_value = header_value.trim();\n\t\tbreak;\n\t}\n}",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.net.ExtractHeader",
+  "inputPorts" : [ {
+    "name" : "headers",
+    "depth" : 1,
+    "type" : "String"
+  }, {
+    "name" : "header_key",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "header_value",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.AskWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.AskWorker.json
new file mode 100644
index 0000000..c2095cc
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.AskWorker.json
@@ -0,0 +1,20 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "import javax.swing.JOptionPane;\n\nanswer = JOptionPane.showInputDialog(null, (message == void ? null : message), (title == void ? null : title), JOptionPane.QUESTION_MESSAGE);\n\n\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.ui.AskWorker",
+  "inputPorts" : [ {
+    "name" : "title",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "message",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "answer",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.ChooseWorker b/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.ChooseWorker
index b45960b..5244d77 100644
--- a/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.ChooseWorker
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.ChooseWorker
@@ -6,6 +6,10 @@
 import javax.swing.JPanel;

 import javax.swing.JRadioButton;

 

+if ((selectionValues == void) || (selectionValues == null) || (selectionValues.isEmpty())) {

+    throw new RuntimeException("selectionValues must be specified and non-empty");

+}

+

 ButtonGroup group = new ButtonGroup();

 JPanel messagePanel = new JPanel();

 messagePanel.setLayout(new BoxLayout(messagePanel,BoxLayout.Y_AXIS));

diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.ChooseWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.ChooseWorker.json
new file mode 100644
index 0000000..0410fc7
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.ChooseWorker.json
@@ -0,0 +1,24 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "import javax.swing.BoxLayout;\nimport javax.swing.ButtonGroup;\nimport javax.swing.JLabel;\nimport javax.swing.JOptionPane;\nimport javax.swing.JPanel;\nimport javax.swing.JRadioButton;\n\nif ((selectionValues == void) || (selectionValues == null) || (selectionValues.isEmpty())) {\n    throw new RuntimeException(\"selectionValues must be specified and non-empty\");\n}\n\nButtonGroup group = new ButtonGroup();\nJPanel messagePanel = new JPanel();\nmessagePanel.setLayout(new BoxLayout(messagePanel,BoxLayout.Y_AXIS));\n\nmessagePanel.add(new JLabel((message == void ? null : message)));\n\t\t\nJRadioButton[] buttonArray = new JRadioButton[selectionValues.size()];\nfor (int i = 0; i < buttonArray.length; i++) {\t\t\t\n\tbuttonArray[i] = new JRadioButton(selectionValues.get(i));\n\tif (i==0) buttonArray[i].setSelected(true);\n\tgroup.add(buttonArray[i]);\n\tmessagePanel.add(buttonArray[i]);\n}\t\t\t\t\n\nJOptionPane.showOptionDialog(null, messagePanel, (title == void ? null : title),\n\t\tJOptionPane.YES_NO_CANCEL_OPTION, JOptionPane.QUESTION_MESSAGE, null, new Object[]{\"OK\"}, null);\n\t\t\nString answer=\"\";\nfor (JRadioButton button : buttonArray) {\n\tif (button.isSelected()) {\n\t\tanswer=button.getText();\n\t}\n}\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.ui.ChooseWorker",
+  "inputPorts" : [ {
+    "name" : "title",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "message",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "selectionValues",
+    "depth" : 1,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "answer",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.SelectFileWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.SelectFileWorker.json
new file mode 100644
index 0000000..1d71cef
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.SelectFileWorker.json
@@ -0,0 +1,24 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "import java.awt.CardLayout;\nimport java.awt.Image;\nimport java.awt.Toolkit;\nimport java.io.File;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport javax.swing.ImageIcon;\nimport javax.swing.JEditorPane;\nimport javax.swing.JFileChooser;\nimport javax.swing.JLabel;\nimport javax.swing.JPanel;\nimport javax.swing.filechooser.FileFilter;\n\nclass FileExtFilter extends FileFilter {\n\n\tpublic FileExtFilter(String ext, String label, boolean includeDir) {\n\t\tthis.ext = ext;\n\t\tthis.label = label;\n\t\tthis.includeDir = includeDir;\n\t}\n\n\tpublic String getDescription() {\n\t\treturn this.label;\n\t}\n\n\tpublic boolean accept(File file) {\n\t\tif (file.isDirectory() && includeDir) {\n\t\t\treturn true;\n\t\t} else {\n\t\t\treturn file.getName().endsWith(this.ext);\n\t\t}\n\t}\n\n\tString ext, label;\n\n\tboolean includeDir;\n}\n\nif (title == void) {\n\ttitle = null;\n}\n\nif ((fileExtensions == void) || (fileExtensions == null)) {\n\tfileExtensions = \"\";\n}\n\nif ((fileExtLabels == void) || (fileExtLabels == null)) {\n\tfileExtLabels = \"\";\n}\n\nJFileChooser chooser = new JFileChooser();\nchooser.setDialogTitle(title);\n\nString[] fileTypeList = fileExtensions.split(\",\");\nString[] filterLabelList = fileExtLabels.split(\",\");\n\nif (fileTypeList != null && filterLabelList != null && fileTypeList.length != filterLabelList.length) {\n\tthrow new RuntimeException(\"The list of extensions and file filter labels must be the same length\");\n}\n\n// create the file filters\nfor (int i = 0; i < fileTypeList.length; i++) {\n\tFileExtFilter filter = new FileExtFilter(fileTypeList[i], filterLabelList[i], true);\n\tchooser.setFileFilter(filter);\n}\n\nchooser.showOpenDialog(null);\nFile file = chooser.getSelectedFile();\nselectedFile = file.getAbsolutePath();\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.ui.SelectFileWorker",
+  "inputPorts" : [ {
+    "name" : "title",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "fileExtensions",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "fileExtLabels",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "selectedFile",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.SelectWorker b/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.SelectWorker
index ed72043..1745844 100644
--- a/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.SelectWorker
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.SelectWorker
@@ -1,6 +1,10 @@
 <activity xmlns="http://taverna.sf.net/2008/xml/t2flow"><class>net.sf.taverna.t2.activities.localworker.LocalworkerActivity</class><inputMap /><outputMap /><configBean encoding="xstream"><net.sf.taverna.t2.activities.localworker.LocalworkerActivityConfigurationBean xmlns="">

   <script>import javax.swing.JOptionPane;

 

+if ((valueList == void) || (valueList == null) || (valueList.isEmpty())) {

+    throw new RuntimeException("valueList must be specified and non-empty");

+}

+

 answer = (String) JOptionPane.showInputDialog(null, (message == void ? null : message), (title == void ? null : title), JOptionPane.QUESTION_MESSAGE, null, valueList.toArray(), valueList.get(0));

 </script>

   <dependencies />

diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.SelectWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.SelectWorker.json
new file mode 100644
index 0000000..6c287b6
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.SelectWorker.json
@@ -0,0 +1,24 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "import javax.swing.JOptionPane;\n\nif ((valueList == void) || (valueList == null) || (valueList.isEmpty())) {\n    throw new RuntimeException(\"valueList must be specified and non-empty\");\n}\n\nanswer = (String) JOptionPane.showInputDialog(null, (message == void ? null : message), (title == void ? null : title), JOptionPane.QUESTION_MESSAGE, null, valueList.toArray(), valueList.get(0));\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.ui.SelectWorker",
+  "inputPorts" : [ {
+    "name" : "valueList",
+    "depth" : 1,
+    "type" : "String"
+  }, {
+    "name" : "message",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "title",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "answer",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.TellWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.TellWorker.json
new file mode 100644
index 0000000..8037a42
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.TellWorker.json
@@ -0,0 +1,20 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "import javax.swing.JOptionPane;\n\nJOptionPane.showMessageDialog(null, (message == void ? null : message), (title == void ? null : title),\tJOptionPane.INFORMATION_MESSAGE);\n\nanswer = \"answer\";\n\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.ui.TellWorker",
+  "inputPorts" : [ {
+    "name" : "title",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "message",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "answer",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.WarnWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.WarnWorker.json
new file mode 100644
index 0000000..eaa8c93
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.ui.WarnWorker.json
@@ -0,0 +1,20 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "import javax.swing.JOptionPane;\n\nJOptionPane.showMessageDialog(null, (message == void ? null : message), (title == void ? null : title),\tJOptionPane.WARNING_MESSAGE);\n\nanswer = \"answer\";\n  \n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.ui.WarnWorker",
+  "inputPorts" : [ {
+    "name" : "title",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "message",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "answer",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.xml.XPathTextWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.xml.XPathTextWorker.json
new file mode 100644
index 0000000..3fa2385
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.xml.XPathTextWorker.json
@@ -0,0 +1,24 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "import org.dom4j.Document;\nimport org.dom4j.Node;\nimport org.dom4j.io.SAXReader;\n\nSAXReader reader = new SAXReader(false);\nreader.setIncludeInternalDTDDeclarations(false);\nreader.setIncludeExternalDTDDeclarations(false);\n\nDocument document = reader.read(new StringReader(xmltext));\nList nodelist = document.selectNodes(xpath);\n\n// Process the elements in the nodelist\nArrayList outputList = new ArrayList();\nArrayList outputXmlList = new ArrayList();\n\nString val = null;\nString xmlVal = null;\nfor (Iterator iter = nodelist.iterator(); iter.hasNext();) {\n\tNode element = (Node) iter.next();\n\txmlVal = element.asXML();\n\tval = element.getStringValue();\n\tif (val != null && !val.equals(\"\")) {\n\t\toutputList.add(val);\n\t\toutputXmlList.add(xmlVal);\n\t}\n\n}\n\nList nodelist=outputList;\nList nodelistAsXML=outputXmlList;",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.xml.XPathTextWorker",
+  "inputPorts" : [ {
+    "name" : "xpath",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "xml-text",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "nodelist",
+    "depth" : 1,
+    "granularDepth" : 1
+  }, {
+    "name" : "nodelistAsXML",
+    "depth" : 1,
+    "granularDepth" : 1
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.xml.XSLTWorker b/src/main/resources/net.sourceforge.taverna.scuflworkers.xml.XSLTWorker
index a405aef..1532b63 100644
--- a/src/main/resources/net.sourceforge.taverna.scuflworkers.xml.XSLTWorker
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.xml.XSLTWorker
@@ -76,7 +76,8 @@
 Transformer xformer = template.newTransformer();

 

 // Prepare the input and output files

-Source source = new StreamSource(getReader(inFileURL));

+Reader sourceReader = getReader(inFileURL);

+Source source = new StreamSource(sourceReader);

 StringWriter resultStr = new StringWriter();

 Result result = new StreamResult(resultStr);

 

@@ -92,7 +93,9 @@
 

 	out.write(outputStr);

 	out.close();

-}</script>

+}

+sourceReader.close();

+</script>

   <dependencies />

   <inputs>

     <net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean>

diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.xml.XSLTWorker.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.xml.XSLTWorker.json
new file mode 100644
index 0000000..09aff0d
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.xml.XSLTWorker.json
@@ -0,0 +1,28 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "import java.io.BufferedReader;\nimport java.io.BufferedWriter;\nimport java.io.FileInputStream;\nimport java.io.FileNotFoundException;\nimport java.io.FileReader;\nimport java.io.FileWriter;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.io.OutputStreamWriter;\nimport java.io.StringWriter;\nimport java.io.Writer;\nimport java.net.URL;\nimport java.util.HashMap;\nimport java.util.Map;\n\nimport javax.xml.transform.Result;\nimport javax.xml.transform.Source;\nimport javax.xml.transform.SourceLocator;\nimport javax.xml.transform.Templates;\nimport javax.xml.transform.Transformer;\nimport javax.xml.transform.TransformerConfigurationException;\nimport javax.xml.transform.TransformerException;\nimport javax.xml.transform.TransformerFactory;\nimport javax.xml.transform.stream.StreamResult;\nimport javax.xml.transform.stream.StreamSource;\n\nBufferedReader getReader (String fileUrl) throws IOException {\n\t\tInputStreamReader reader;\n\t\ttry {\n\t\t\treader = new FileReader(fileUrl);\n\t\t}\n\t\tcatch (FileNotFoundException e) {\n\t\t\t// try a real URL instead\n\t\t\tURL url = new URL(fileUrl);\n\t\t\treader = new InputStreamReader (url.openStream());\n\t\t}\n\t\treturn new BufferedReader(reader);\n\t}\n\t\nBufferedWriter getWriter (String fileUrl) throws IOException {\n\t\tWriter writer;\n\t\ttry {\n\t\t\twriter = new FileWriter(fileUrl);\n\t\t}\n\t\tcatch (FileNotFoundException e) {\n\t\t\t// try a real URL instead\n\t\t\tURL url = new URL(fileUrl);\n\t\t\twriter = new OutputStreamWriter (url.openConnection().getOutputStream());\n\t\t}\n\t\treturn new BufferedWriter(writer);\n\t}\n\t\nString xslFilename = xslFileURL;\nString outFilename;\nif (outFileURL != void) {\n    outFilename = outFileURL;\n}\n\nString ext;\nif (outputExt != void) {\n    ext = outputExt;\n}\n\nif (((outFilename == null) || outFilename.equals(\"\")) && (ext != null)) {\n\t\toutFilename = inFileURL.substring(0, inFileURL.indexOf(\".\")+1) + ext;\n}\n\n// Create transformer factory\nTransformerFactory factory = TransformerFactory.newInstance();\n\n// Use the factory to create a template containing the xsl file\nTemplates template = factory.newTemplates(new StreamSource(getReader(xslFilename)));\n\n// Use the template to create a transformer\nTransformer xformer = template.newTransformer();\n\n// Prepare the input and output files\nReader sourceReader = getReader(inFileURL);\nSource source = new StreamSource(sourceReader);\nStringWriter resultStr = new StringWriter();\nResult result = new StreamResult(resultStr);\n\n// Apply the xsl file to the source file and write the result to the\n// output file\nxformer.transform(source, result);\n\noutputStr = resultStr.toString();\n\nif ((outFilename != null) && !outFilename.equals(\"\")) {\n\n\tBufferedWriter out = getWriter(outFilename);\n\n\tout.write(outputStr);\n\tout.close();\n}\nsourceReader.close();\n",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.xml.XSLTWorker",
+  "inputPorts" : [ {
+    "name" : "xslFileURL",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "outFileURL",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "inFileURL",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "outputExt",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "outputStr",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.xml.XSLTWorkerWithParameters b/src/main/resources/net.sourceforge.taverna.scuflworkers.xml.XSLTWorkerWithParameters
new file mode 100644
index 0000000..768c8f9
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.xml.XSLTWorkerWithParameters
@@ -0,0 +1,100 @@
+<activity xmlns="http://taverna.sf.net/2008/xml/t2flow">
+  <class>net.sf.taverna.t2.activities.localworker.LocalworkerActivity</class>
+  <inputMap>
+    <map from="xsltString" to="xsltString" />
+    <map from="paramList" to="paramList" />
+    <map from="sourceString" to="sourceString" />
+  </inputMap>
+  <outputMap>
+    <map from="outputString" to="outputString" />
+  </outputMap>
+  <configBean encoding="xstream">
+    <net.sf.taverna.t2.activities.localworker.LocalworkerActivityConfigurationBean xmlns="">
+  <inputs>
+    <net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean>
+      <name>sourceString</name>
+      <depth>0</depth>
+      <mimeTypes>
+        <string>text/plain</string>
+      </mimeTypes>
+      <handledReferenceSchemes />
+      <translatedElementType>java.lang.String</translatedElementType>
+      <allowsLiteralValues>true</allowsLiteralValues>
+    </net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean>
+    <net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean>
+      <name>xsltString</name>
+      <depth>0</depth>
+      <mimeTypes>
+        <string>text/plain</string>
+      </mimeTypes>
+      <handledReferenceSchemes />
+      <translatedElementType>java.lang.String</translatedElementType>
+      <allowsLiteralValues>true</allowsLiteralValues>
+    </net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean>
+    <net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean>
+      <name>paramList</name>
+      <depth>1</depth>
+      <mimeTypes>
+        <string>text/plain</string>
+      </mimeTypes>
+      <handledReferenceSchemes />
+      <translatedElementType>java.lang.String</translatedElementType>
+      <allowsLiteralValues>true</allowsLiteralValues>
+    </net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean>
+  </inputs>
+  <outputs>
+    <net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityOutputPortDefinitionBean>
+      <name>outputString</name>
+      <depth>0</depth>
+      <mimeTypes />
+      <granularDepth>0</granularDepth>
+    </net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityOutputPortDefinitionBean>
+  </outputs>
+  <classLoaderSharing>workflow</classLoaderSharing>
+  <localDependencies />
+  <artifactDependencies />
+  <script>//From a proposal by Mikolaj Rybinski
+import javax.xml.transform.Source;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.transform.stream.StreamSource;
+
+param(paramstr) {
+    nameAndValue = paramstr.split("=");
+    if (nameAndValue.length != 2) {
+        throw new RuntimeException("Wrong parameter format: \"" + paramstr + "\".");
+    }
+    name = nameAndValue[0].trim();
+    value = nameAndValue[1].trim();
+    return this;
+}
+
+if ((sourceString == void) || (sourceString == null)) {
+        throw new RuntimeException("sourceString must be specified");
+}
+
+if ((xsltString == void) || (xsltString == null)) {
+        throw new RuntimeException("xsltString must be specified");
+}
+
+Source inSource = new StreamSource(new StringReader(sourceString));
+Source xslSource = new StreamSource(new StringReader(xsltString));
+
+// the factory pattern supports different XSLT processors
+// e.g. set the "javax.xml.transform.TransformerFactory" system property
+TransformerFactory tnfFact = TransformerFactory.newInstance();
+Transformer tnf = tnfFact.newTransformer(xslSource);
+
+if (paramList != void) {
+  for (String paramstr : paramList) {
+    p = param(paramstr);
+    tnf.setParameter(p.name, p.value);
+  }
+}
+
+Writer outputWriter = new StringWriter();
+tnf.transform(inSource, new StreamResult(outputWriter));
+outputString = outputWriter.toString();</script>
+  <dependencies />
+</net.sf.taverna.t2.activities.localworker.LocalworkerActivityConfigurationBean></configBean><annotations /></activity>
diff --git a/src/main/resources/net.sourceforge.taverna.scuflworkers.xml.XSLTWorkerWithParameters.json b/src/main/resources/net.sourceforge.taverna.scuflworkers.xml.XSLTWorkerWithParameters.json
new file mode 100644
index 0000000..0800c76
--- /dev/null
+++ b/src/main/resources/net.sourceforge.taverna.scuflworkers.xml.XSLTWorkerWithParameters.json
@@ -0,0 +1,24 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "//From a proposal by Mikolaj Rybinski\nimport javax.xml.transform.Source;\nimport javax.xml.transform.Transformer;\nimport javax.xml.transform.TransformerFactory;\nimport javax.xml.transform.stream.StreamResult;\nimport javax.xml.transform.stream.StreamSource;\n\nparam(paramstr) {\n    nameAndValue = paramstr.split(\"=\");\n    if (nameAndValue.length != 2) {\n        throw new RuntimeException(\"Wrong parameter format: \\\"\" + paramstr + \"\\\".\");\n    }\n    name = nameAndValue[0].trim();\n    value = nameAndValue[1].trim();\n    return this;\n}\n\nif ((sourceString == void) || (sourceString == null)) {\n        throw new RuntimeException(\"sourceString must be specified\");\n}\n\nif ((xsltString == void) || (xsltString == null)) {\n        throw new RuntimeException(\"xsltString must be specified\");\n}\n\nSource inSource = new StreamSource(new StringReader(sourceString));\nSource xslSource = new StreamSource(new StringReader(xsltString));\n\n// the factory pattern supports different XSLT processors\n// e.g. set the \"javax.xml.transform.TransformerFactory\" system property\nTransformerFactory tnfFact = TransformerFactory.newInstance();\nTransformer tnf = tnfFact.newTransformer(xslSource);\n\nif (paramList != void) {\n  for (String paramstr : paramList) {\n    p = param(paramstr);\n    tnf.setParameter(p.name, p.value);\n  }\n}\n\nWriter outputWriter = new StringWriter();\ntnf.transform(inSource, new StreamResult(outputWriter));\noutputString = outputWriter.toString();",
+  "localworkerName" : "net.sourceforge.taverna.scuflworkers.xml.XSLTWorkerWithParameters",
+  "inputPorts" : [ {
+    "name" : "sourceString",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "xsltString",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "paramList",
+    "depth" : 1,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "outputString",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.ByteArrayToString b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.ByteArrayToString
index 61acb18..35b50d0 100644
--- a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.ByteArrayToString
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.ByteArrayToString
@@ -1,5 +1,12 @@
 <activity xmlns="http://taverna.sf.net/2008/xml/t2flow"><class>net.sf.taverna.t2.activities.localworker.LocalworkerActivity</class><inputMap /><outputMap /><configBean encoding="xstream"><net.sf.taverna.t2.activities.localworker.LocalworkerActivityConfigurationBean xmlns="">

-  <script>string = new String(bytes);

+  <script>if ((bytes == void) || (bytes == null)) {

+	throw new RuntimeException("The 'bytes' parameter must be specified");

+}

+if (encoding == void) {

+	string = new String(bytes);

+} else {

+	string = new String(bytes, encoding);

+}

 </script>

   <dependencies />

   <inputs>

@@ -13,6 +20,16 @@
         <string>'application/octet-stream'</string>

       </mimeTypes>

     </net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean>

+    <net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean>

+      <handledReferenceSchemes />

+      <translatedElementType>java.lang.String</translatedElementType>

+      <allowsLiteralValues>true</allowsLiteralValues>

+      <name>encoding</name>

+      <depth>0</depth>

+      <mimeTypes>

+        <string>'text/plain'</string>

+      </mimeTypes>

+    </net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityInputPortDefinitionBean>

   </inputs>

   <outputs>

     <net.sf.taverna.t2.workflowmodel.processor.activity.config.ActivityOutputPortDefinitionBean>

diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.ByteArrayToString.json b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.ByteArrayToString.json
new file mode 100644
index 0000000..ae7f934
--- /dev/null
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.ByteArrayToString.json
@@ -0,0 +1,20 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "if ((bytes == void) || (bytes == null)) {\n\tthrow new RuntimeException(\"The 'bytes' parameter must be specified\");\n}\nif (encoding == void) {\n\tstring = new String(bytes);\n} else {\n\tstring = new String(bytes, encoding);\n}\n",
+  "localworkerName" : "org.embl.ebi.escience.scuflworkers.java.ByteArrayToString",
+  "inputPorts" : [ {
+    "name" : "bytes",
+    "depth" : 0,
+    "type" : "byte[]"
+  }, {
+    "name" : "encoding",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "string",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.DecodeBase64.json b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.DecodeBase64.json
new file mode 100644
index 0000000..1cb0f62
--- /dev/null
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.DecodeBase64.json
@@ -0,0 +1,16 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "import org.apache.commons.codec.binary.Base64;\n\nbytes = Base64.decodeBase64(base64.getBytes());\n",
+  "localworkerName" : "org.embl.ebi.escience.scuflworkers.java.DecodeBase64",
+  "inputPorts" : [ {
+    "name" : "base64",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "bytes",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.EchoList.json b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.EchoList.json
new file mode 100644
index 0000000..aa0d198
--- /dev/null
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.EchoList.json
@@ -0,0 +1,16 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "outputlist = inputlist;",
+  "localworkerName" : "org.embl.ebi.escience.scuflworkers.java.EchoList",
+  "inputPorts" : [ {
+    "name" : "inputlist",
+    "depth" : 1,
+    "type" : "byte[]"
+  } ],
+  "outputPorts" : [ {
+    "name" : "outputlist",
+    "depth" : 1,
+    "granularDepth" : 1
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.EmitLotsOfStrings.json b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.EmitLotsOfStrings.json
new file mode 100644
index 0000000..4afc1f8
--- /dev/null
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.EmitLotsOfStrings.json
@@ -0,0 +1,11 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "List strings = new ArrayList();\nfor (int i = 0; i < 40; i++) {\n\tstrings.add(\"String\" + i);\n}\n",
+  "localworkerName" : "org.embl.ebi.escience.scuflworkers.java.EmitLotsOfStrings",
+  "outputPorts" : [ {
+    "name" : "strings",
+    "depth" : 1,
+    "granularDepth" : 1
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.EncodeBase64.json b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.EncodeBase64.json
new file mode 100644
index 0000000..5cbd786
--- /dev/null
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.EncodeBase64.json
@@ -0,0 +1,16 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "import org.apache.commons.codec.binary.Base64;\n\nbase64 = new String(Base64.encodeBase64(bytes));",
+  "localworkerName" : "org.embl.ebi.escience.scuflworkers.java.EncodeBase64",
+  "inputPorts" : [ {
+    "name" : "bytes",
+    "depth" : 0,
+    "type" : "byte[]"
+  } ],
+  "outputPorts" : [ {
+    "name" : "base64",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.ExtractImageLinks.json b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.ExtractImageLinks.json
new file mode 100644
index 0000000..2a23a47
--- /dev/null
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.ExtractImageLinks.json
@@ -0,0 +1,16 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "String lowerCaseContent = document.toLowerCase();\nint index = 0;\nList imagelinks = new ArrayList();\nwhile ((index = lowerCaseContent.indexOf(\"<img\", index)) != -1) {\n\tif ((index = lowerCaseContent.indexOf(\"src\", index)) == -1)\n\t\tbreak;\n\tif ((index = lowerCaseContent.indexOf(\"=\", index)) == -1)\n\t\tbreak;\n\tindex++;\n\tString remaining = document.substring(index);\n\tStringTokenizer st = new StringTokenizer(remaining, \"\\t\\n\\r\\\">#\");\n\tString strLink = st.nextToken();\n\timagelinks.add(strLink);\n}\n\n",
+  "localworkerName" : "org.embl.ebi.escience.scuflworkers.java.ExtractImageLinks",
+  "inputPorts" : [ {
+    "name" : "document",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "imagelinks",
+    "depth" : 1,
+    "granularDepth" : 1
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.FilterStringList.json b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.FilterStringList.json
new file mode 100644
index 0000000..0f26e3e
--- /dev/null
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.FilterStringList.json
@@ -0,0 +1,20 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "filteredlist = new ArrayList();\nfor (Iterator i = stringlist.iterator(); i.hasNext();) {\n\tString item = (String) i.next();\n\tif (item.matches(regex)) {\n\t\tfilteredlist.add(item);\n\t}\n}\n",
+  "localworkerName" : "org.embl.ebi.escience.scuflworkers.java.FilterStringList",
+  "inputPorts" : [ {
+    "name" : "stringlist",
+    "depth" : 1,
+    "type" : "String"
+  }, {
+    "name" : "regex",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "filteredlist",
+    "depth" : 1,
+    "granularDepth" : 1
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.FlattenList.json b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.FlattenList.json
new file mode 100644
index 0000000..4992e0b
--- /dev/null
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.FlattenList.json
@@ -0,0 +1,16 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "flatten(inputs, outputs, depth) {\n\tfor (i = inputs.iterator(); i.hasNext();) {\n\t    element = i.next();\n\t\tif (element instanceof Collection && depth > 0) {\n\t\t\tflatten(element, outputs, depth - 1);\n\t\t} else {\n\t\t\toutputs.add(element);\n\t\t}\n\t}\n}\n\noutputlist = new ArrayList();\n\nflatten(inputlist, outputlist, 1);",
+  "localworkerName" : "org.embl.ebi.escience.scuflworkers.java.FlattenList",
+  "inputPorts" : [ {
+    "name" : "inputlist",
+    "depth" : 2,
+    "type" : "byte[]"
+  } ],
+  "outputPorts" : [ {
+    "name" : "outputlist",
+    "depth" : 1,
+    "granularDepth" : 1
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.PadNumber.json b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.PadNumber.json
new file mode 100644
index 0000000..37828ea
--- /dev/null
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.PadNumber.json
@@ -0,0 +1,20 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "int targetLengthInt = 7;\nif (targetlength != void) {\n\ttargetLengthInt = Integer.parseInt(targetlength);\n}\nint currentLength = input.length();\nwhile (input.length() < targetLengthInt) {\n\tinput = \"0\" + input;\n}\npadded = input;",
+  "localworkerName" : "org.embl.ebi.escience.scuflworkers.java.PadNumber",
+  "inputPorts" : [ {
+    "name" : "input",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "targetlength",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "padded",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.RegularExpressionStringList.json b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.RegularExpressionStringList.json
new file mode 100644
index 0000000..86378fb
--- /dev/null
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.RegularExpressionStringList.json
@@ -0,0 +1,24 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "import java.util.regex.*;\n\nfilteredlist = new ArrayList();\nPattern thePat = Pattern.compile(regex);\nint theGroup = Integer.parseInt(group);\n\nfor (Iterator i = stringlist.iterator(); i.hasNext();) {\n\tString item = (String) i.next();\n\tMatcher matcher = thePat.matcher(item);\n\n\tif (matcher.find()) {\n\t\tfilteredlist.add(matcher.group(theGroup));\n\t}\n}\n",
+  "localworkerName" : "org.embl.ebi.escience.scuflworkers.java.RegularExpressionStringList",
+  "inputPorts" : [ {
+    "name" : "stringlist",
+    "depth" : 1,
+    "type" : "String"
+  }, {
+    "name" : "regex",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "group",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "filteredlist",
+    "depth" : 1,
+    "granularDepth" : 1
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.SendEmail.json b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.SendEmail.json
new file mode 100644
index 0000000..9a7365d
--- /dev/null
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.SendEmail.json
@@ -0,0 +1,27 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "import javax.mail.Message;\nimport javax.mail.Session;\nimport javax.mail.Transport;\nimport javax.mail.internet.MimeMessage;\nimport javax.mail.internet.InternetAddress;\n\nif (subject == void) {\n\tsubject = \"No subject\";\n}\nif (body == void) {\n\tthrow new Exception(\"No body specified for message\");\n}\n\nProperties mailProps = System.getProperties();\nif (smtpserver != void) {\n\tmailProps.put(\"mail.smtp.host\", smtpserver);\n}\n\nSession session = Session.getDefaultInstance(mailProps, null);\nMimeMessage message = new MimeMessage(session);\nmessage.setFrom(new InternetAddress(from));\nmessage.addRecipient(Message.RecipientType.TO, new InternetAddress(to));\nmessage.setSubject(subject);\nmessage.setText(body);\nTransport.send(message);\n",
+  "localworkerName" : "org.embl.ebi.escience.scuflworkers.java.SendEmail",
+  "inputPorts" : [ {
+    "name" : "to",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "from",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "subject",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "body",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "smtpserver",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.SplitByRegex.json b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.SplitByRegex.json
new file mode 100644
index 0000000..afbdc78
--- /dev/null
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.SplitByRegex.json
@@ -0,0 +1,20 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "List split = new ArrayList();\nif (!string.equals(\"\")) {\n\tString regexString = \",\";\n\tif (regex != void) {\n\t\tregexString = regex;\n\t}\n\tString[] result = string.split(regexString);\n\tfor (int i = 0; i < result.length; i++) {\n\t\tsplit.add(result[i]);\n\t}\n}\n",
+  "localworkerName" : "org.embl.ebi.escience.scuflworkers.java.SplitByRegex",
+  "inputPorts" : [ {
+    "name" : "string",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "regex",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "split",
+    "depth" : 1,
+    "granularDepth" : 1
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.StringConcat.json b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.StringConcat.json
new file mode 100644
index 0000000..24a3fa9
--- /dev/null
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.StringConcat.json
@@ -0,0 +1,20 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "output = string1 + string2;",
+  "localworkerName" : "org.embl.ebi.escience.scuflworkers.java.StringConcat",
+  "inputPorts" : [ {
+    "name" : "string1",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "string2",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "output",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.StringListMerge.json b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.StringListMerge.json
new file mode 100644
index 0000000..a0b860f
--- /dev/null
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.StringListMerge.json
@@ -0,0 +1,20 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "String seperatorString = \"\\n\";\nif (seperator != void) {\n\tseperatorString = seperator;\n}\nStringBuffer sb = new StringBuffer();\nfor (Iterator i = stringlist.iterator(); i.hasNext();) {\n\tString item = (String) i.next();\n\tsb.append(item);\n\tif (i.hasNext()) {\n\t\tsb.append(seperatorString);\n\t}\n}\nconcatenated = sb.toString();\n",
+  "localworkerName" : "org.embl.ebi.escience.scuflworkers.java.StringListMerge",
+  "inputPorts" : [ {
+    "name" : "stringlist",
+    "depth" : 1,
+    "type" : "String"
+  }, {
+    "name" : "seperator",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "concatenated",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.StringSetDifference.json b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.StringSetDifference.json
new file mode 100644
index 0000000..c844322
--- /dev/null
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.StringSetDifference.json
@@ -0,0 +1,20 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "List difference = new ArrayList();\nfor (Iterator i = list1.iterator(); i.hasNext();) {\n\tObject o = i.next();\n\tif (!list2.contains(o)) {\n\t\tdifference.add(o);\n\t}\n}\nfor (Iterator i = list2.iterator(); i.hasNext();) {\n\tObject o = i.next();\n\tif (!list1.contains(o)) {\n\t\tdifference.add(o);\n\t}\n}\n",
+  "localworkerName" : "org.embl.ebi.escience.scuflworkers.java.StringSetDifference",
+  "inputPorts" : [ {
+    "name" : "list1",
+    "depth" : 1,
+    "type" : "String"
+  }, {
+    "name" : "list2",
+    "depth" : 1,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "difference",
+    "depth" : 1,
+    "granularDepth" : 1
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.StringSetIntersection.json b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.StringSetIntersection.json
new file mode 100644
index 0000000..0404922
--- /dev/null
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.StringSetIntersection.json
@@ -0,0 +1,20 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "List intersection = new ArrayList();\nfor (Iterator i = list1.iterator(); i.hasNext();) {\n\tObject o = i.next();\n\tif (list2.contains(o)) {\n\t\tintersection.add(o);\n\t}\n}\n",
+  "localworkerName" : "org.embl.ebi.escience.scuflworkers.java.StringSetIntersection",
+  "inputPorts" : [ {
+    "name" : "list1",
+    "depth" : 1,
+    "type" : "String"
+  }, {
+    "name" : "list2",
+    "depth" : 1,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "intersection",
+    "depth" : 1,
+    "granularDepth" : 1
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.StringSetUnion.json b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.StringSetUnion.json
new file mode 100644
index 0000000..25960be
--- /dev/null
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.StringSetUnion.json
@@ -0,0 +1,20 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "Set results = new HashSet();\nresults.addAll(list1);\nresults.addAll(list2);\nList union = new ArrayList();\nunion.addAll(results);\n",
+  "localworkerName" : "org.embl.ebi.escience.scuflworkers.java.StringSetUnion",
+  "inputPorts" : [ {
+    "name" : "list1",
+    "depth" : 1,
+    "type" : "String"
+  }, {
+    "name" : "list2",
+    "depth" : 1,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "union",
+    "depth" : 1,
+    "granularDepth" : 1
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.StringStripDuplicates.json b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.StringStripDuplicates.json
new file mode 100644
index 0000000..c5fecee
--- /dev/null
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.StringStripDuplicates.json
@@ -0,0 +1,16 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "List strippedlist = new ArrayList();\nfor (Iterator i = stringlist.iterator(); i.hasNext();) {\n\tString item = (String) i.next();\n\tif (strippedlist.contains(item) == false) {\n\t\tstrippedlist.add(item);\n\t}\n}\n",
+  "localworkerName" : "org.embl.ebi.escience.scuflworkers.java.StringStripDuplicates",
+  "inputPorts" : [ {
+    "name" : "stringlist",
+    "depth" : 1,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "strippedlist",
+    "depth" : 1,
+    "granularDepth" : 1
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.TestAlwaysFailingProcessor.json b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.TestAlwaysFailingProcessor.json
new file mode 100644
index 0000000..4a5b7d8
--- /dev/null
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.TestAlwaysFailingProcessor.json
@@ -0,0 +1,20 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "throw new Exception(\"This script fails\");",
+  "localworkerName" : "org.embl.ebi.escience.scuflworkers.java.TestAlwaysFailingProcessor",
+  "inputPorts" : [ {
+    "name" : "foo",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "bar",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "urgle",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.TestSometimesFails.json b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.TestSometimesFails.json
new file mode 100644
index 0000000..9ecf11d
--- /dev/null
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.TestSometimesFails.json
@@ -0,0 +1,16 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "import java.util.Random;\n\nRandom r = new Random();\n\nif ((r.nextInt() % 4) == 0) {\n\tthrow new RuntimeException(\"Fails every four runs!\");\n}\n\nout = in;",
+  "localworkerName" : "org.embl.ebi.escience.scuflworkers.java.TestSometimesFails",
+  "inputPorts" : [ {
+    "name" : "in",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "out",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.WebImageFetcher b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.WebImageFetcher
index ea26a07..db3a73a 100644
--- a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.WebImageFetcher
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.WebImageFetcher
@@ -1,36 +1,32 @@
 <activity xmlns="http://taverna.sf.net/2008/xml/t2flow"><class>net.sf.taverna.t2.activities.localworker.LocalworkerActivity</class><inputMap /><outputMap /><configBean encoding="xstream"><net.sf.taverna.t2.activities.localworker.LocalworkerActivityConfigurationBean xmlns="">

-  <script>URL inputURL = null;

+  <script>if ((url == void) || (url == null)) {

+	throw new RuntimeException("The url must be specified");

+}

+

+URL inputURL = null;

 if (base != void) {

 	inputURL = new URL(new URL(base), url);

 } else {

 	inputURL = new URL(url);

 }

 

-byte[] contents;

-if (inputURL.openConnection().getContentLength() == -1) {

-	// Content size unknown, must read first...

-	byte[] buffer = new byte[1024];

-	int bytesRead = 0;

-	int totalBytesRead = 0;

-	InputStream is = inputURL.openStream();

-	while (bytesRead != -1) {

-		totalBytesRead += bytesRead;

-		bytesRead = is.read(buffer, 0, 1024);

-	}

-	contents = new byte[totalBytesRead];

-} else {

-	contents = new byte[inputURL.openConnection().getContentLength()];

-}

 int bytesRead = 0;

 int totalBytesRead = 0;

 InputStream is = inputURL.openStream();

-while (bytesRead != -1) {

-	bytesRead = is.read(contents, totalBytesRead, contents.length - totalBytesRead);

-	totalBytesRead += bytesRead;

-	if (contents.length==totalBytesRead) break;

+ByteArrayOutputStream os = new ByteArrayOutputStream();

+byte[] buffer = new byte[2048];

+while (true) {

+	bytesRead = is.read(buffer);

+	if (bytesRead == -1) {

+		break;	

+	}

+

+	os.write(buffer, 0, bytesRead);

 }

 

-image = contents;

+image = os.toByteArray();

+is.close();

+os.close();

 </script>

   <dependencies />

   <inputs>

diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.WebImageFetcher.json b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.WebImageFetcher.json
new file mode 100644
index 0000000..a65b448
--- /dev/null
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.WebImageFetcher.json
@@ -0,0 +1,20 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "if ((url == void) || (url == null)) {\n\tthrow new RuntimeException(\"The url must be specified\");\n}\n\nURL inputURL = null;\nif (base != void) {\n\tinputURL = new URL(new URL(base), url);\n} else {\n\tinputURL = new URL(url);\n}\n\nint bytesRead = 0;\nint totalBytesRead = 0;\nInputStream is = inputURL.openStream();\nByteArrayOutputStream os = new ByteArrayOutputStream();\nbyte[] buffer = new byte[2048];\nwhile (true) {\n\tbytesRead = is.read(buffer);\n\tif (bytesRead == -1) {\n\t\tbreak;\t\n\t}\n\n\tos.write(buffer, 0, bytesRead);\n}\n\nimage = os.toByteArray();\nis.close();\nos.close();\n",
+  "localworkerName" : "org.embl.ebi.escience.scuflworkers.java.WebImageFetcher",
+  "inputPorts" : [ {
+    "name" : "url",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "base",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "image",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.WebPageFetcher b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.WebPageFetcher
index 5752124..dcd76a6 100644
--- a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.WebPageFetcher
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.WebPageFetcher
@@ -1,5 +1,9 @@
 <activity xmlns="http://taverna.sf.net/2008/xml/t2flow"><class>net.sf.taverna.t2.activities.localworker.LocalworkerActivity</class><inputMap /><outputMap /><configBean encoding="xstream"><net.sf.taverna.t2.activities.localworker.LocalworkerActivityConfigurationBean xmlns="">

-  <script>URL inputURL = null;

+  <script>if ((url == void) || (url == null)) {

+	throw new RuntimeException("The url must be specified");

+}

+

+URL inputURL = null;

 if (base != void) {

   inputURL = new URL(new URL(base), url);

 }

@@ -9,35 +13,24 @@
 URLConnection con = inputURL.openConnection();

 InputStream in = con.getInputStream();

 

-InputStreamReader isr = new InputStreamReader(in);

-Reader inReader = new BufferedReader(isr);

+StringBuffer result = new StringBuffer();

+BufferedReader reader;

 

-StringBuffer buf = new StringBuffer();

-int ch;

-while ((ch = inReader.read()) &gt; -1) {

-  buf.append((char)ch);

+String encoding = con.getContentEncoding();

+if (encoding == null) {

+  reader = new BufferedReader(new InputStreamReader(in));

+} else {

+  reader = new BufferedReader(new InputStreamReader(in, encoding));

 }

-inReader.close();

-contents = buf.toString();

+String line = null;

+String NEWLINE = System.getProperty("line.separator");

+while ((line = reader.readLine()) != null) {

+	result.append(line);

+	result.append(NEWLINE);

+}

 

-

-//String NEWLINE = System.getProperty("line.separator");

-//

-//URL inputURL = null;

-//if (base != void) {

-//	inputURL = new URL(new URL(base), url);

-//} else {

-//	inputURL = new URL(url);

-//}

-//StringBuffer result = new StringBuffer();

-//BufferedReader reader = new BufferedReader(new InputStreamReader(inputURL.openStream()));

-//String line = null;

-//while ((line = reader.readLine()) != null) {

-//	result.append(line);

-//	result.append(NEWLINE);

-//}

-//

-//contents = result.toString();

+reader.close();

+contents = result.toString();

 </script>

   <dependencies />

   <inputs>

diff --git a/src/main/resources/org.embl.ebi.escience.scuflworkers.java.WebPageFetcher.json b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.WebPageFetcher.json
new file mode 100644
index 0000000..ad7a5b6
--- /dev/null
+++ b/src/main/resources/org.embl.ebi.escience.scuflworkers.java.WebPageFetcher.json
@@ -0,0 +1,20 @@
+{
+  "classLoaderSharing" : "workflow",
+  "script" : "if ((url == void) || (url == null)) {\n\tthrow new RuntimeException(\"The url must be specified\");\n}\n\nURL inputURL = null;\nif (base != void) {\n  inputURL = new URL(new URL(base), url);\n}\nelse {\n  inputURL = new URL(url);\n}\nURLConnection con = inputURL.openConnection();\nInputStream in = con.getInputStream();\n\nStringBuffer result = new StringBuffer();\nBufferedReader reader;\n\nString encoding = con.getContentEncoding();\nif (encoding == null) {\n  reader = new BufferedReader(new InputStreamReader(in));\n} else {\n  reader = new BufferedReader(new InputStreamReader(in, encoding));\n}\nString line = null;\nString NEWLINE = System.getProperty(\"line.separator\");\nwhile ((line = reader.readLine()) != null) {\n\tresult.append(line);\n\tresult.append(NEWLINE);\n}\n\nreader.close();\ncontents = result.toString();\n",
+  "localworkerName" : "org.embl.ebi.escience.scuflworkers.java.WebPageFetcher",
+  "inputPorts" : [ {
+    "name" : "url",
+    "depth" : 0,
+    "type" : "String"
+  }, {
+    "name" : "base",
+    "depth" : 0,
+    "type" : "String"
+  } ],
+  "outputPorts" : [ {
+    "name" : "contents",
+    "depth" : 0,
+    "granularDepth" : 0
+  } ],
+  "isAltered" : false
+}
\ No newline at end of file
diff --git a/src/test/java/net/sf/taverna/t2/activities/localworker/views/TestContextualViewFactory.java b/src/test/java/net/sf/taverna/t2/activities/localworker/views/TestContextualViewFactory.java
deleted file mode 100644
index 07182a5..0000000
--- a/src/test/java/net/sf/taverna/t2/activities/localworker/views/TestContextualViewFactory.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*******************************************************************************
- * 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 net.sf.taverna.t2.activities.localworker.views;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertTrue;
-
-import java.util.List;
-
-import net.sf.taverna.t2.activities.beanshell.views.BeanshellActivityViewFactory;
-import net.sf.taverna.t2.activities.localworker.LocalworkerActivity;
-import net.sf.taverna.t2.activities.localworker.LocalworkerActivityConfigurationBean;
-import net.sf.taverna.t2.workbench.ui.views.contextualviews.ContextualView;
-import net.sf.taverna.t2.workbench.ui.views.contextualviews.activity.ContextualViewFactory;
-import net.sf.taverna.t2.workbench.ui.views.contextualviews.activity.ContextualViewFactoryRegistry;
-
-import org.junit.Test;
-
-public class TestContextualViewFactory {
-
-	@SuppressWarnings("unchecked")
-	@Test
-	public void getLocalworkerFactoryAndConfigure() throws Exception {
-		LocalworkerActivity localworkerActivity = new LocalworkerActivity();
-		LocalworkerActivityConfigurationBean bean = new LocalworkerActivityConfigurationBean();
-		localworkerActivity.configure(bean);
-
-		List<ContextualViewFactory> viewFactoriesForBeanType = ContextualViewFactoryRegistry.getInstance().getViewFactoriesForObject(localworkerActivity);
-		assertTrue("The localworker view factory should not be empty", !viewFactoriesForBeanType.isEmpty());
-		LocalworkerActivityViewFactory factory = null;
-		for (ContextualViewFactory cvf : viewFactoriesForBeanType) {
-			if (cvf instanceof LocalworkerActivityViewFactory) {
-				factory = (LocalworkerActivityViewFactory) cvf;
-			}
-		}
-		assertTrue("No localworker view factory", factory != null);
-	}
-
-}