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

[04/52] [abbrv] incubator-taverna-workbench git commit: taverna-ui-impl/

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-update-manager/src/main/resources/META-INF/spring/update-manager-context.xml
----------------------------------------------------------------------
diff --git a/taverna-workbench-update-manager/src/main/resources/META-INF/spring/update-manager-context.xml b/taverna-workbench-update-manager/src/main/resources/META-INF/spring/update-manager-context.xml
new file mode 100644
index 0000000..c3adf1f
--- /dev/null
+++ b/taverna-workbench-update-manager/src/main/resources/META-INF/spring/update-manager-context.xml
@@ -0,0 +1,12 @@
+<?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="UpdateMenuAction"
+		class="net.sf.taverna.t2.workbench.update.impl.menu.UpdateMenuAction">
+		<property name="updateManager" ref="updateManager" />
+	</bean>
+
+</beans>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-workbench-impl/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-workbench-workbench-impl/pom.xml b/taverna-workbench-workbench-impl/pom.xml
new file mode 100644
index 0000000..5b52d3a
--- /dev/null
+++ b/taverna-workbench-workbench-impl/pom.xml
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>net.sf.taverna.t2</groupId>
+		<artifactId>ui-impl</artifactId>
+		<version>2.0-SNAPSHOT</version>
+	</parent>
+	<groupId>net.sf.taverna.t2.ui-impl</groupId>
+	<artifactId>workbench-impl</artifactId>
+	<packaging>bundle</packaging>
+	<name>Workbench UI implementation</name>
+	<description>The main workbench ui</description>
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.felix</groupId>
+				<artifactId>maven-bundle-plugin</artifactId>
+				<configuration>
+					<instructions>
+						<Embed-Dependency>osxapplication</Embed-Dependency>
+						<Import-Package>com.apple.eawt;resolution:=optional,*</Import-Package>
+					</instructions>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+	<dependencies>
+		<dependency>
+			<groupId>net.sf.taverna.t2.ui-api</groupId>
+			<artifactId>workbench-api</artifactId>
+			<version>${t2.ui.api.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.taverna.t2.ui-api</groupId>
+			<artifactId>edits-api</artifactId>
+			<version>${t2.ui.api.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.taverna.t2.ui-api</groupId>
+			<artifactId>configuration-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>helper-api</artifactId>
+			<version>${t2.ui.api.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.taverna.t2.ui-api</groupId>
+			<artifactId>menu-api</artifactId>
+			<version>${t2.ui.api.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.taverna.t2.ui-api</groupId>
+			<artifactId>selection-api</artifactId>
+			<version>${t2.ui.api.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.taverna.t2.lang</groupId>
+			<artifactId>observer</artifactId>
+			<version>${t2.lang.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.taverna.t2.lang</groupId>
+			<artifactId>ui</artifactId>
+			<version>${t2.lang.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>uk.org.taverna.commons</groupId>
+			<artifactId>taverna-plugin-api</artifactId>
+			<version>${taverna.commons.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>uk.org.taverna.configuration</groupId>
+			<artifactId>taverna-configuration-api</artifactId>
+			<version>${taverna.configuration.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>commons-io</groupId>
+			<artifactId>commons-io</artifactId>
+		</dependency>
+		<dependency>
+			<groupId>log4j</groupId>
+			<artifactId>log4j</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>junit</groupId>
+			<artifactId>junit</artifactId>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>org.simplericity.macify</groupId>
+			<artifactId>macify</artifactId>
+			<version>1.6</version>
+		</dependency>
+	</dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/DataflowEditsListener.java
----------------------------------------------------------------------
diff --git a/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/DataflowEditsListener.java b/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/DataflowEditsListener.java
new file mode 100644
index 0000000..4c493d1
--- /dev/null
+++ b/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/DataflowEditsListener.java
@@ -0,0 +1,93 @@
+package net.sf.taverna.t2.workbench.ui.impl;
+
+import static uk.org.taverna.scufl2.api.container.WorkflowBundle.generateIdentifier;
+
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+import net.sf.taverna.t2.lang.observer.Observable;
+import net.sf.taverna.t2.lang.observer.Observer;
+import net.sf.taverna.t2.workbench.edits.Edit;
+import net.sf.taverna.t2.workbench.edits.EditManager;
+import net.sf.taverna.t2.workbench.edits.EditManager.AbstractDataflowEditEvent;
+import net.sf.taverna.t2.workbench.edits.EditManager.DataFlowRedoEvent;
+import net.sf.taverna.t2.workbench.edits.EditManager.DataFlowUndoEvent;
+import net.sf.taverna.t2.workbench.edits.EditManager.DataflowEditEvent;
+import net.sf.taverna.t2.workbench.edits.EditManager.EditManagerEvent;
+import net.sf.taverna.t2.workflow.edits.UpdateDataflowInternalIdentifierEdit;
+
+import org.apache.log4j.Logger;
+
+import uk.org.taverna.scufl2.api.container.WorkflowBundle;
+
+/**
+ * Listens out for any edits on a dataflow and changes its internal id (or back
+ * to the old one in the case of redo/undo). Is first created when the workbench
+ * is initialised.
+ * 
+ * @author Ian Dunlop
+ */
+public class DataflowEditsListener implements Observer<EditManagerEvent> {
+	private static Logger logger = Logger
+			.getLogger(DataflowEditsListener.class);
+
+	private Map<Edit<?>, URI> dataflowEditMap;
+
+	public DataflowEditsListener() {
+		super();
+		dataflowEditMap = new HashMap<>();
+	}
+
+	/**
+	 * Receives {@link EditManagerEvent}s from the {@link EditManager} and
+	 * changes the id of the {@link Dataflow} to a new one or back to its old
+	 * one depending on whether it is a do/undo/redo event. Stores the actual
+	 * edit and the pre-edit dataflow id in a Map and changes the id when it
+	 * gets further actions against this same edit
+	 */
+	@Override
+	public void notify(Observable<EditManagerEvent> observable,
+			EditManagerEvent event) throws Exception {
+		Edit<?> edit = event.getEdit();
+		WorkflowBundle dataFlow = ((AbstractDataflowEditEvent) event)
+				.getDataFlow();
+
+		if (event instanceof DataflowEditEvent) {
+			/*
+			 * the dataflow has been edited in some way so change its internal
+			 * id and store the old one against the edit that is changing
+			 * 'something'
+			 */
+			URI internalIdentifier = dataFlow.getGlobalBaseURI();
+			dataflowEditMap.put(edit, internalIdentifier);
+			URI newIdentifier = generateIdentifier();
+			new UpdateDataflowInternalIdentifierEdit(dataFlow, newIdentifier)
+					.doEdit();
+			logger.debug("Workflow edit, id changed from: "
+					+ internalIdentifier + " to " + newIdentifier);
+		} else if (event instanceof DataFlowRedoEvent) {
+			/*
+			 * change the id back to the old one and store the new one in case
+			 * we want to change it back
+			 */
+			URI newId = dataFlow.getGlobalBaseURI();
+			URI oldId = dataflowEditMap.get(edit);
+			dataflowEditMap.put(edit, newId);
+			new UpdateDataflowInternalIdentifierEdit(dataFlow, oldId).doEdit();
+			logger.debug("Workflow edit, id changed from: " + newId + " to "
+					+ oldId);
+		} else if (event instanceof DataFlowUndoEvent) {
+			/*
+			 * change the id back to the old one and store the new one in case
+			 * we want to change it back
+			 */
+			URI newId = dataFlow.getGlobalBaseURI();
+			URI oldId = dataflowEditMap.get(edit);
+			dataflowEditMap.put(edit, newId);
+			new UpdateDataflowInternalIdentifierEdit(dataFlow, oldId).doEdit();
+			logger.debug("Workflow edit, id changed from: " + newId + " to "
+					+ oldId);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/LoggerStream.java
----------------------------------------------------------------------
diff --git a/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/LoggerStream.java b/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/LoggerStream.java
new file mode 100644
index 0000000..fe13d4d
--- /dev/null
+++ b/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/LoggerStream.java
@@ -0,0 +1,136 @@
+/***************************************
+ *                                     *
+ *  JBoss: The OpenSource J2EE WebOS   *
+ *                                     *
+ *  Distributable under LGPL license.  *
+ *  See terms of license at gnu.org.   *
+ *                                     *
+ *  Modified by Stian Soiland-Reyes    *
+ *                                     *
+ ***************************************/
+package net.sf.taverna.t2.workbench.ui.impl;
+
+import java.io.IOException;
+import java.io.PrintStream;
+
+import org.apache.log4j.Logger;
+import org.apache.log4j.Level;
+
+/**
+ * A subclass of PrintStream that redirects its output to a log4j Logger.
+ *
+ * <p>This class is used to map PrintStream/PrintWriter oriented logging onto
+ *    the log4j Categories. Examples include capturing System.out/System.err
+ *
+ * @version <tt>$Revision: 1.1.1.1 $</tt>
+ * @author <a href="mailto:Scott.Stark@jboss.org">Scott Stark</a>.
+ * @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
+ */
+//FIXME Replace this class entirely
+class LoggerStream extends PrintStream {
+	/**
+	 * Default flag to enable/disable tracing println calls. from the system
+	 * property <tt>net.sf.taverna.t2.workbench.ui.impl.LoggerStream.trace</tt>
+	 * or if not set defaults to <tt>false</tt>.
+	 */
+   public static final boolean TRACE =
+		   getBoolean(LoggerStream.class.getName() + ".trace", false);
+
+	/**
+	 * Helper to get boolean value from system property or use default if not
+	 * set.
+	 */
+	private static boolean getBoolean(String name, boolean defaultValue) {
+		String value = System.getProperty(name, null);
+		if (value == null)
+			return defaultValue;
+		return new Boolean(value).booleanValue();
+	}
+
+	private Logger logger;
+	private Level level;
+	private boolean issuedWarning;
+
+	/**
+	 * Redirect logging to the indicated logger using Level.INFO
+	 */
+	public LoggerStream(Logger logger) {
+		this(logger, Level.INFO, System.out);
+	}
+
+	/**
+	 * Redirect logging to the indicated logger using the given level. The ps is
+	 * simply passed to super but is not used.
+	 */
+	public LoggerStream(Logger logger, Level level, PrintStream ps) {
+		super(ps);
+		this.logger = logger;
+		this.level = level;
+	}
+
+	@Override
+	public void println(String msg) {
+		if (msg == null)
+			msg = "null";
+		byte[] bytes = msg.getBytes();
+		write(bytes, 0, bytes.length);
+	}
+
+	@Override
+	public void println(Object msg) {
+		if (msg == null)
+			msg = "null";
+		byte[] bytes = msg.toString().getBytes();
+		write(bytes, 0, bytes.length);
+	}
+
+	public void write(byte b) {
+		byte[] bytes = { b };
+		write(bytes, 0, 1);
+	}
+
+	private ThreadLocal<Boolean> recursiveCheck = new ThreadLocal<>();
+
+	@Override
+	public void write(byte[] b, int off, int len) {
+		Boolean recursed = recursiveCheck.get();
+		if (recursed != null && recursed) {
+			/*
+			 * There is a configuration error that is causing looping. Most
+			 * likely there are two console appenders so just return to prevent
+			 * spinning.
+			 */
+			if (issuedWarning == false) {
+				String msg = "ERROR: invalid log settings detected, console capturing is looping";
+				// out.write(msg.getBytes());
+				new Exception(msg).printStackTrace((PrintStream) out);
+				issuedWarning = true;
+			}
+			try {
+				out.write(b, off, len);
+			} catch (IOException e) {
+			}
+			return;
+		}
+
+		// Remove the end of line chars
+		while (len > 0 && (b[len - 1] == '\n' || b[len - 1] == '\r')
+				&& len > off)
+			len--;
+
+		/*
+		 * HACK, something is logging exceptions line by line (including
+		 * blanks), but I can't seem to find it, so for now just ignore empty
+		 * lines... they aren't very useful.
+		 */
+		if (len != 0) {
+			String msg = new String(b, off, len);
+			recursiveCheck.set(true);
+			if (TRACE)
+				logger.log(level, msg, new Throwable());
+			else
+				logger.log(level, msg);
+			recursiveCheck.set(false);
+		}
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/SetConsoleLoggerStartup.java
----------------------------------------------------------------------
diff --git a/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/SetConsoleLoggerStartup.java b/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/SetConsoleLoggerStartup.java
new file mode 100644
index 0000000..a8bdfdd
--- /dev/null
+++ b/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/SetConsoleLoggerStartup.java
@@ -0,0 +1,62 @@
+package net.sf.taverna.t2.workbench.ui.impl;
+
+import static org.apache.log4j.Level.ERROR;
+import static org.apache.log4j.Level.WARN;
+
+import java.io.PrintStream;
+
+import net.sf.taverna.t2.workbench.StartupSPI;
+import net.sf.taverna.t2.workbench.configuration.workbench.WorkbenchConfiguration;
+
+import org.apache.log4j.ConsoleAppender;
+import org.apache.log4j.Logger;
+
+public class SetConsoleLoggerStartup implements StartupSPI {
+	private static final PrintStream originalErr = System.err;
+	private static final PrintStream originalOut = System.out;
+
+	private final WorkbenchConfiguration workbenchConfiguration;
+
+	public SetConsoleLoggerStartup(WorkbenchConfiguration workbenchConfiguration) {
+		this.workbenchConfiguration = workbenchConfiguration;
+	}
+
+	@Override
+	public int positionHint() {
+		/*
+		 * Must be <b>after</b> PrepareLoggerStarup in file-translator --
+		 * otherwise Taverna 1 libraries will cause double logging
+		 */
+		return 10;
+	}
+
+	@Override
+	public boolean startup() {
+		setSystemOutCapture();
+		return true;
+	}
+
+	public void setSystemOutCapture() {
+		if (!workbenchConfiguration.getCaptureConsole()) {
+			System.setOut(originalOut);
+			System.setErr(originalErr);
+			return;
+		}
+		Logger systemOutLogger = Logger.getLogger("System.out");
+		Logger systemErrLogger = Logger.getLogger("System.err");
+
+		try {
+			/*
+			 * This logger stream not loop with log4j > 1.2.13, which has
+			 * getFollow method
+			 */
+			ConsoleAppender.class.getMethod("getFollow");
+			System.setOut(new LoggerStream(systemOutLogger, WARN, originalOut));
+		} catch (SecurityException e) {
+		} catch (NoSuchMethodException e) {
+			System.err.println("Not capturing System.out, use log4j >= 1.2.13");
+		}
+
+		System.setErr(new LoggerStream(systemErrLogger, ERROR, originalErr));
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/StoreWindowStateOnShutdown.java
----------------------------------------------------------------------
diff --git a/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/StoreWindowStateOnShutdown.java b/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/StoreWindowStateOnShutdown.java
new file mode 100644
index 0000000..2537f0b
--- /dev/null
+++ b/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/StoreWindowStateOnShutdown.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (C) 2008-2010 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.impl;
+
+import org.apache.log4j.Logger;
+
+import net.sf.taverna.t2.workbench.ShutdownSPI;
+import net.sf.taverna.t2.workbench.ui.Workbench;
+
+/**
+ * Store Workbench window size and perspectives, so that settings can be used on
+ * next startup.
+ * 
+ * @author Stian Soiland-Reyes
+ */
+public class StoreWindowStateOnShutdown implements ShutdownSPI {
+	private static Logger logger = Logger
+			.getLogger(StoreWindowStateOnShutdown.class);
+
+	private Workbench workbench;
+
+	@Override
+	public int positionHint() {
+		return 1000;
+	}
+
+	@Override
+	public boolean shutdown() {
+		try {
+			workbench.storeSizeAndLocationPrefs();
+		} catch (Exception ex) {
+			logger.error("Error saving the Workbench size and position", ex);
+		}
+		return true;
+	}
+
+	public void setWorkbench(Workbench workbench) {
+		this.workbench = workbench;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/UserRegistrationData.java
----------------------------------------------------------------------
diff --git a/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/UserRegistrationData.java b/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/UserRegistrationData.java
new file mode 100644
index 0000000..3e32f7b
--- /dev/null
+++ b/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/UserRegistrationData.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * 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.workbench.ui.impl;
+
+public class UserRegistrationData {
+	private String tavernaVersion = "";
+	private String firstName = "";
+	private String lastName = "";
+	private String emailAddress = "";
+	private String institutionOrCompanyName = "";
+	private String industry = "";
+	private String field = "";
+	private String purposeOfUsingTaverna = "";
+	private boolean keepMeInformed = false;
+
+	public void setTavernaVersion(String tavernaVersion) {
+		this.tavernaVersion = tavernaVersion;
+	}
+
+	public String getTavernaVersion() {
+		return tavernaVersion;
+	}
+
+	public void setFirstName(String firstName) {
+		this.firstName = firstName;
+	}
+
+	public String getFirstName() {
+		return firstName;
+	}
+
+	public void setLastName(String lastName) {
+		this.lastName = lastName;
+	}
+
+	public String getLastName() {
+		return lastName;
+	}
+
+	public void setEmailAddress(String emailAddress) {
+		this.emailAddress = emailAddress;
+	}
+
+	public String getEmailAddress() {
+		return emailAddress;
+	}
+
+	public void setInstitutionOrCompanyName(String institutionOrCompanyName) {
+		this.institutionOrCompanyName = institutionOrCompanyName;
+	}
+
+	public String getInstitutionOrCompanyName() {
+		return institutionOrCompanyName;
+	}
+
+	public void setIndustry(String industry) {
+		this.industry = industry;
+	}
+
+	public String getIndustry() {
+		return industry;
+	}
+
+	public void setField(String field) {
+		this.field = field;
+	}
+
+	public String getField() {
+		return field;
+	}
+
+	public void setPurposeOfUsingTaverna(String purposeOfUsingTaverna) {
+		this.purposeOfUsingTaverna = purposeOfUsingTaverna;
+	}
+
+	public String getPurposeOfUsingTaverna() {
+		return purposeOfUsingTaverna;
+	}
+
+	public void setKeepMeInformed(boolean keepMeInformed) {
+		this.keepMeInformed = keepMeInformed;
+	}
+
+	public boolean getKeepMeInformed() {
+		return keepMeInformed;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/UserRegistrationForm.java
----------------------------------------------------------------------
diff --git a/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/UserRegistrationForm.java b/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/UserRegistrationForm.java
new file mode 100644
index 0000000..97f831f
--- /dev/null
+++ b/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/UserRegistrationForm.java
@@ -0,0 +1,995 @@
+/*******************************************************************************
+ * 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.workbench.ui.impl;
+
+import static java.awt.BorderLayout.CENTER;
+import static java.awt.BorderLayout.NORTH;
+import static java.awt.Color.LIGHT_GRAY;
+import static java.awt.Color.WHITE;
+import static java.awt.FlowLayout.LEFT;
+import static java.awt.Font.BOLD;
+import static java.awt.GridBagConstraints.FIRST_LINE_START;
+import static java.awt.GridBagConstraints.HORIZONTAL;
+import static java.awt.GridBagConstraints.LINE_START;
+import static java.awt.GridBagConstraints.NONE;
+import static java.awt.GridBagConstraints.WEST;
+import static java.awt.event.KeyEvent.VK_ENTER;
+import static java.awt.event.KeyEvent.VK_TAB;
+import static javax.swing.JOptionPane.ERROR_MESSAGE;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static javax.swing.SwingConstants.BOTTOM;
+import static javax.swing.SwingConstants.TOP;
+import static javax.swing.event.HyperlinkEvent.EventType.ACTIVATED;
+import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.tavernaCogs32x32Icon;
+
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Desktop;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.Frame;
+import java.awt.Graphics;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.Rectangle;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.net.ConnectException;
+import java.net.MalformedURLException;
+import java.net.SocketTimeoutException;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLConnection;
+import java.net.URLEncoder;
+import java.util.Properties;
+
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JEditorPane;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.border.Border;
+import javax.swing.event.HyperlinkEvent;
+import javax.swing.event.HyperlinkListener;
+import javax.swing.text.Document;
+import javax.swing.text.html.HTMLEditorKit;
+import javax.swing.text.html.StyleSheet;
+
+import net.sf.taverna.t2.lang.ui.DialogTextArea;
+import net.sf.taverna.t2.workbench.helper.HelpEnabledDialog;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.log4j.Logger;
+/**
+ * User registration form.
+ * 
+ * @author Alex Nenadic
+ */
+@SuppressWarnings("serial")
+public class UserRegistrationForm extends HelpEnabledDialog {
+	private static final String FAILED = "User registration failed: ";
+
+	private static final String REGISTRATION_FAILED_MSG = "User registration failed. Please try again later.";
+
+	private static final String REGISTRATION_URL = "http://www.mygrid.org.uk/taverna/registration/";
+
+	public static final String TAVERNA_VERSION_PROPERTY_NAME = "Taverna version";
+	public static final String FIRST_NAME_PROPERTY_NAME = "First name";
+	public static final String LAST_NAME_PROPERTY_NAME = "Last name";
+	public static final String EMAIL_ADDRESS_PROPERTY_NAME = "Email address";
+	public static final String INSTITUTION_OR_COMPANY_PROPERTY_NAME = "Institution or company name";
+	public static final String INDUSTRY_PROPERTY_NAME = "Industry";
+	public static final String FIELD_PROPERTY_NAME = "Field of investigation";
+	public static final String PURPOSE_PROPERTY_NAME = "Purpose of using Taverna";
+	public static final String KEEP_ME_INFORMED_PROPERTY_NAME = "Keep me informed by email";
+
+	public static final String TAVERNA_REGISTRATION_POST_PARAMETER_NAME = "taverna_registration";
+	public static final String TAVERNA_VERSION_POST_PARAMETER_NAME = "taverna_version";
+	public static final String FIRST_NAME_POST_PARAMETER_NAME = "first_name";
+	public static final String LAST_NAME_POST_PARAMETER_NAME = "last_name";
+	public static final String EMAIL_ADDRESS_POST_PARAMETER_NAME = "email";
+	public static final String INSTITUTION_OR_COMPANY_POST_PARAMETER_NAME = "institution_or_company";
+	public static final String INDUSTRY_TYPE_POST_PARAMETER_NAME = "industry_type";
+	public static final String FIELD_POST_PARAMETER_NAME = "field";
+	public static final String PURPOSE_POST_PARAMETER_NAME = "purpose";
+	public static final String KEEP_ME_INFORMED_POST_PARAMETER_PROPERTY_NAME = "keep_me_informed";
+
+	private static String TRUE = Boolean.TRUE.toString();
+	private static String FALSE = Boolean.FALSE.toString();
+
+	private static final String WELCOME = "Welcome to the Taverna User Registration Form";
+	private static final String PLEASE_FILL_IN_THIS_REGISTRATION_FORM = "Please fill in this registration form to let us know that you are using Taverna";
+
+	private static final String WE_DO = "Note that by registering:\n"
+			+ "   \u25CF We do not have access to your data\n"
+			+ "   \u25CF We do not have access to your service usage\n"
+			+ "   \u25CF You will not be monitored\n"
+			+ "   \u25CF We do record the information you provide\n"
+			+ "     at registration time";
+
+	private static final String WHY_REGISTER = "By registering you will:\n"
+			+ "   \u25CF Allow us to support you better; future plans will be\n"
+			+ "     directed towards solutions Taverna users require\n"
+			+ "   \u25CF Help sustain Taverna development; our continued\n"
+			+ "     funding relies on us showing usage\n"
+			+ "   \u25CF (Optionally) Hear about news and product updates";
+
+	private static final String FIRST_NAME = "*First name:";
+	private static final String LAST_NAME = "*Last name:";
+	private static final String EMAIL_ADDRESS = "*Email address:";
+	private static final String KEEP_ME_INFORMED = "Keep me informed of news and product updates via email";
+	private static final String INSTITUTION_COMPANY_NAME = "*Institution/Company name:";
+	private static final String FIELD_OF_INVESTIGATION = " Field of investigation:\n"
+			+ " (e.g. bioinformatics)";
+	private static final String WHY_YOU_INTEND_TO_USE_TAVERNA = " A brief description of how you intend\n"
+			+ " to use Taverna: (e.g. genome analysis\n"
+			+ " for bacterial strain identification)";
+
+	private static String[] industryTypes = { "", "Academia - Life Sciences",
+			"Academia - Social Sciences", "Academia - Physical Sciences",
+			"Academia - Environmental Sciences", "Academia - Other",
+			"Industry - Biotechnology", "Industry - Pharmaceutical",
+			"Industry - Engineering", "Industry - Other",
+			"Healthcare Services", "Goverment and Public Sector", "Other" };
+
+	private static final String I_AGREE_TO_THE_TERMS_AND_CONDITIONS = "I agree to the terms and conditions of registration at";
+	private static final String TERMS_AND_CONDITIONS_URL = "http://www.taverna.org.uk/legal/terms";
+
+	private Logger logger = Logger.getLogger(UserRegistrationForm.class);
+	private UserRegistrationData previousRegistrationData;
+	private JTextField firstNameTextField;
+	private JTextField lastNameTextField;
+	private JTextField emailTextField;
+	private JCheckBox keepMeInformedCheckBox;
+	private JTextField institutionOrCompanyTextField;
+	private JComboBox<String> industryTypeTextField;
+	private JTextField fieldTextField;
+	private JTextArea purposeTextArea;
+	private JCheckBox termsAndConditionsCheckBox;
+
+	private final File registrationDataFile;
+	private final File remindMeLaterFile;
+	private final File doNotRegisterMeFile;
+	private final String appName;
+
+	public UserRegistrationForm(String appName, File registrationDataFile,
+			File doNotRegisterMeFile, File remindMeLaterFile) {
+		super((Frame) null, "Taverna User Registration", true);
+		this.appName = appName;
+		this.registrationDataFile = registrationDataFile;
+		this.doNotRegisterMeFile = doNotRegisterMeFile;
+		this.remindMeLaterFile = remindMeLaterFile;
+		initComponents();
+	}
+
+	public UserRegistrationForm(String appName,
+			File previousRegistrationDataFile, File registrationDataFile,
+			File doNotRegisterMeFile, File remindMeLaterFile) {
+		super((Frame) null, "Taverna User Registration", true);
+		this.appName = appName;
+		this.registrationDataFile = registrationDataFile;
+		this.doNotRegisterMeFile = doNotRegisterMeFile;
+		this.remindMeLaterFile = remindMeLaterFile;
+		previousRegistrationData = loadUserRegistrationData(previousRegistrationDataFile);
+		initComponents();
+	}
+
+	// For testing only
+	// public static void main(String[] args) throws ClassNotFoundException,
+	// InstantiationException, IllegalAccessException,
+	// UnsupportedLookAndFeelException{
+	// WorkbenchImpl.setLookAndFeel();
+	// UserRegistrationForm form = new UserRegistrationForm();
+	// form.setVisible(true);
+	// }
+
+	private void initComponents() {
+		JPanel mainPanel = new JPanel(new GridBagLayout());
+
+		// Base font for all components on the form
+		Font baseFont = new JLabel("base font").getFont().deriveFont(11f);
+
+		// Title panel
+		JPanel titlePanel = new JPanel(new FlowLayout(LEFT));
+		titlePanel.setBackground(WHITE);
+		// titlePanel.setBorder(new EmptyBorder(10, 10, 10, 10));
+		JLabel titleLabel = new JLabel(WELCOME);
+		titleLabel.setFont(baseFont.deriveFont(BOLD, 13.5f));
+		// titleLabel.setBorder(new EmptyBorder(10, 10, 0, 10));
+		JLabel titleIcon = new JLabel(tavernaCogs32x32Icon);
+		// titleIcon.setBorder(new EmptyBorder(10, 10, 10, 10));
+		DialogTextArea titleMessage = new DialogTextArea(
+				PLEASE_FILL_IN_THIS_REGISTRATION_FORM);
+		titleMessage.setMargin(new Insets(0, 20, 0, 10));
+		titleMessage.setFont(baseFont);
+		titleMessage.setEditable(false);
+		titleMessage.setFocusable(false);
+		// titlePanel.setBorder( new EmptyBorder(10, 10, 0, 10));
+		JPanel messagePanel = new JPanel(new BorderLayout());
+		messagePanel.add(titleLabel, NORTH);
+		messagePanel.add(titleMessage, CENTER);
+		messagePanel.setBackground(WHITE);
+		titlePanel.add(titleIcon);
+		titlePanel.add(messagePanel);
+		addDivider(titlePanel, BOTTOM, true);
+
+		GridBagConstraints gbc = new GridBagConstraints();
+		gbc.weightx = 1.0;
+		gbc.weighty = 0.0;
+		gbc.gridx = 0;
+		gbc.gridy = 0;
+		gbc.fill = HORIZONTAL;
+		gbc.anchor = WEST;
+		gbc.gridwidth = 2;
+		// gbc.insets = new Insets(5, 10, 0, 0);
+		mainPanel.add(titlePanel, gbc);
+
+		// Registration messages
+		gbc.weightx = 0.0;
+		gbc.weighty = 0.0;
+		gbc.gridx = 0;
+		gbc.gridy = 1;
+		gbc.fill = NONE;
+		gbc.anchor = WEST;
+		gbc.gridwidth = 2;
+		// gbc.insets = new Insets(5, 0, 0, 10);
+		DialogTextArea registrationMessage1 = new DialogTextArea(WHY_REGISTER);
+		registrationMessage1.setMargin(new Insets(0, 10, 0, 0));
+		registrationMessage1.setFont(baseFont);
+		registrationMessage1.setEditable(false);
+		registrationMessage1.setFocusable(false);
+		registrationMessage1.setBackground(getBackground());
+
+		DialogTextArea registrationMessage2 = new DialogTextArea(WE_DO);
+		registrationMessage2.setMargin(new Insets(0, 10, 0, 10));
+		registrationMessage2.setFont(baseFont);
+		registrationMessage2.setEditable(false);
+		registrationMessage2.setFocusable(false);
+		registrationMessage2.setBackground(getBackground());
+		JPanel registrationMessagePanel = new JPanel(new FlowLayout(
+				FlowLayout.CENTER));
+		registrationMessagePanel.add(registrationMessage1);
+		registrationMessagePanel.add(registrationMessage2);
+		addDivider(registrationMessagePanel, BOTTOM, true);
+		mainPanel.add(registrationMessagePanel, gbc);
+
+		// Mandatory label
+		// JLabel mandatoryLabel = new JLabel("* Mandatory fields");
+		// mandatoryLabel.setFont(baseFont);
+		// gbc.weightx = 0.0;
+		// gbc.weighty = 0.0;
+		// gbc.gridx = 0;
+		// gbc.gridy = 3;
+		// gbc.fill = NONE;
+		// gbc.anchor = GridBagConstraints.EAST;
+		// gbc.gridwidth = 2;
+		// gbc.insets = new Insets(0, 10, 0, 20);
+		// mainPanel.add(mandatoryLabel, gbc);
+
+		// First name
+		JLabel firstNameLabel = new JLabel(FIRST_NAME);
+		firstNameLabel.setFont(baseFont);
+		gbc.weightx = 0.0;
+		gbc.weighty = 0.0;
+		gbc.gridx = 0;
+		gbc.gridy = 4;
+		gbc.fill = NONE;
+		gbc.anchor = WEST;
+		gbc.gridwidth = 1;
+		gbc.insets = new Insets(0, 10, 0, 10);
+		mainPanel.add(firstNameLabel, gbc);
+
+		firstNameTextField = new JTextField();
+		firstNameTextField.setFont(baseFont);
+		if (previousRegistrationData != null)
+			firstNameTextField.setText(previousRegistrationData.getFirstName());
+		gbc.weightx = 1.0;
+		gbc.weighty = 0.0;
+		gbc.gridx = 1;
+		gbc.gridy = 4;
+		gbc.fill = HORIZONTAL;
+		gbc.anchor = WEST;
+		gbc.gridwidth = 1;
+		gbc.insets = new Insets(5, 10, 0, 10);
+		mainPanel.add(firstNameTextField, gbc);
+
+		// Last name
+		JLabel lastNameLabel = new JLabel(LAST_NAME);
+		lastNameLabel.setFont(baseFont);
+		gbc.weightx = 0.0;
+		gbc.weighty = 0.0;
+		gbc.gridx = 0;
+		gbc.gridy = 5;
+		gbc.fill = NONE;
+		gbc.anchor = WEST;
+		gbc.gridwidth = 1;
+		gbc.insets = new Insets(0, 10, 0, 10);
+		mainPanel.add(lastNameLabel, gbc);
+
+		lastNameTextField = new JTextField();
+		lastNameTextField.setFont(baseFont);
+		if (previousRegistrationData != null)
+			lastNameTextField.setText(previousRegistrationData.getLastName());
+		gbc.weightx = 1.0;
+		gbc.weighty = 0.0;
+		gbc.gridx = 1;
+		gbc.gridy = 5;
+		gbc.fill = HORIZONTAL;
+		gbc.anchor = WEST;
+		gbc.gridwidth = 1;
+		gbc.insets = new Insets(5, 10, 0, 10);
+		mainPanel.add(lastNameTextField, gbc);
+
+		// Email address
+		JLabel emailLabel = new JLabel(EMAIL_ADDRESS);
+		emailLabel.setFont(baseFont);
+		gbc.weightx = 0.0;
+		gbc.weighty = 0.0;
+		gbc.gridx = 0;
+		gbc.gridy = 6;
+		gbc.fill = NONE;
+		gbc.anchor = WEST;
+		gbc.gridwidth = 1;
+		gbc.insets = new Insets(5, 10, 0, 10);
+		mainPanel.add(emailLabel, gbc);
+
+		emailTextField = new JTextField();
+		emailTextField.setFont(baseFont);
+		if (previousRegistrationData != null)
+			emailTextField.setText(previousRegistrationData.getEmailAddress());
+		gbc.weightx = 1.0;
+		gbc.weighty = 0.0;
+		gbc.gridx = 1;
+		gbc.gridy = 6;
+		gbc.fill = HORIZONTAL;
+		gbc.anchor = WEST;
+		gbc.gridwidth = 1;
+		gbc.insets = new Insets(5, 10, 0, 10);
+		mainPanel.add(emailTextField, gbc);
+
+		// Keep me informed
+		keepMeInformedCheckBox = new JCheckBox(KEEP_ME_INFORMED);
+		keepMeInformedCheckBox.setFont(baseFont);
+		if (previousRegistrationData != null)
+			keepMeInformedCheckBox.setSelected(previousRegistrationData
+					.getKeepMeInformed());
+		keepMeInformedCheckBox.addKeyListener(new KeyAdapter() {
+			@Override
+			public void keyPressed(KeyEvent evt) {
+				if (evt.getKeyCode() == VK_ENTER) {
+					evt.consume();
+					keepMeInformedCheckBox.setSelected(!keepMeInformedCheckBox
+							.isSelected());
+				}
+			}
+		});
+		gbc.weightx = 0.0;
+		gbc.weighty = 0.0;
+		gbc.gridx = 1;
+		gbc.gridy = 7;
+		gbc.fill = NONE;
+		gbc.anchor = WEST;
+		gbc.gridwidth = 2;
+		gbc.insets = new Insets(5, 10, 0, 10);
+		mainPanel.add(keepMeInformedCheckBox, gbc);
+
+		// Institution name
+		JLabel institutionLabel = new JLabel(INSTITUTION_COMPANY_NAME);
+		institutionLabel.setFont(baseFont);
+		gbc.weightx = 0.0;
+		gbc.weighty = 0.0;
+		gbc.gridx = 0;
+		gbc.gridy = 8;
+		gbc.fill = NONE;
+		gbc.anchor = WEST;
+		gbc.gridwidth = 1;
+		gbc.insets = new Insets(5, 10, 0, 10);
+		mainPanel.add(institutionLabel, gbc);
+
+		institutionOrCompanyTextField = new JTextField();
+		institutionOrCompanyTextField.setFont(baseFont);
+		if (previousRegistrationData != null)
+			institutionOrCompanyTextField.setText(previousRegistrationData
+					.getInstitutionOrCompanyName());
+		gbc.weightx = 1.0;
+		gbc.weighty = 0.0;
+		gbc.gridx = 1;
+		gbc.gridy = 8;
+		gbc.fill = HORIZONTAL;
+		gbc.anchor = WEST;
+		gbc.gridwidth = 1;
+		gbc.insets = new Insets(5, 10, 0, 10);
+		mainPanel.add(institutionOrCompanyTextField, gbc);
+
+		// Industry type
+		JLabel industryLabel = new JLabel(" Industry type:");
+		industryLabel.setFont(baseFont);
+		gbc.weightx = 0.0;
+		gbc.weighty = 0.0;
+		gbc.gridx = 0;
+		gbc.gridy = 9;
+		gbc.fill = NONE;
+		gbc.anchor = WEST;
+		gbc.gridwidth = 1;
+		gbc.insets = new Insets(5, 10, 0, 10);
+		mainPanel.add(industryLabel, gbc);
+
+		industryTypeTextField = new JComboBox<>(industryTypes);
+		industryTypeTextField.setFont(baseFont);
+		if (previousRegistrationData != null)
+			industryTypeTextField.setSelectedItem(previousRegistrationData
+					.getIndustry());
+		gbc.weightx = 1.0;
+		gbc.weighty = 0.0;
+		gbc.gridx = 1;
+		gbc.gridy = 9;
+		gbc.fill = HORIZONTAL;
+		gbc.anchor = WEST;
+		gbc.gridwidth = 1;
+		gbc.insets = new Insets(5, 10, 0, 10);
+		mainPanel.add(industryTypeTextField, gbc);
+
+		// Field of investigation
+		JTextArea fieldLabel = new JTextArea(FIELD_OF_INVESTIGATION);
+		fieldLabel.setFont(baseFont);
+		fieldLabel.setEditable(false);
+		fieldLabel.setFocusable(false);
+		fieldLabel.setBackground(getBackground());
+		gbc.weightx = 0.0;
+		gbc.weighty = 0.0;
+		gbc.gridx = 0;
+		gbc.gridy = 10;
+		gbc.fill = NONE;
+		gbc.anchor = LINE_START;
+		gbc.gridwidth = 1;
+		gbc.insets = new Insets(5, 10, 0, 10);
+		mainPanel.add(fieldLabel, gbc);
+
+		fieldTextField = new JTextField();
+		fieldTextField.setFont(baseFont);
+		if (previousRegistrationData != null)
+			fieldTextField.setText(previousRegistrationData.getField());
+		gbc.weightx = 1.0;
+		gbc.weighty = 0.0;
+		gbc.gridx = 1;
+		gbc.gridy = 10;
+		gbc.fill = HORIZONTAL;
+		gbc.anchor = FIRST_LINE_START;
+		gbc.gridwidth = 1;
+		gbc.insets = new Insets(5, 10, 0, 10);
+		mainPanel.add(fieldTextField, gbc);
+
+		// Purpose of using Taverna
+		JTextArea purposeLabel = new JTextArea(WHY_YOU_INTEND_TO_USE_TAVERNA);
+		purposeLabel.setFont(baseFont);
+		purposeLabel.setEditable(false);
+		purposeLabel.setFocusable(false);
+		purposeLabel.setBackground(getBackground());
+		gbc.weightx = 0.0;
+		gbc.weighty = 0.0;
+		gbc.gridx = 0;
+		gbc.gridy = 11;
+		gbc.fill = NONE;
+		gbc.anchor = LINE_START;
+		gbc.gridwidth = 1;
+		gbc.insets = new Insets(5, 10, 0, 10);
+		mainPanel.add(purposeLabel, gbc);
+
+		purposeTextArea = new JTextArea(4, 30);
+		purposeTextArea.setFont(baseFont);
+		purposeTextArea.setLineWrap(true);
+		purposeTextArea.setAutoscrolls(true);
+		if (previousRegistrationData != null)
+			purposeTextArea.setText(previousRegistrationData
+					.getPurposeOfUsingTaverna());
+		purposeTextArea.addKeyListener(new KeyAdapter() {
+			@Override
+			public void keyPressed(KeyEvent evt) {
+				if (evt.getKeyCode() == VK_TAB) {
+					if (evt.getModifiers() > 0)
+						purposeTextArea.transferFocusBackward();
+					else
+						purposeTextArea.transferFocus();
+					evt.consume();
+				}
+			}
+		});
+		JScrollPane purposeScrollPane = new JScrollPane(purposeTextArea);
+		gbc.weightx = 1.0;
+		gbc.weighty = 0.0;
+		gbc.gridx = 1;
+		gbc.gridy = 11;
+		gbc.fill = HORIZONTAL;
+		gbc.anchor = FIRST_LINE_START;
+		gbc.gridwidth = 1;
+		gbc.insets = new Insets(5, 10, 0, 10);
+		mainPanel.add(purposeScrollPane, gbc);
+
+		// Terms and conditions
+		termsAndConditionsCheckBox = new JCheckBox(
+				I_AGREE_TO_THE_TERMS_AND_CONDITIONS);
+		termsAndConditionsCheckBox.setFont(baseFont);
+		termsAndConditionsCheckBox.setBorder(null);
+		termsAndConditionsCheckBox.addKeyListener(new KeyAdapter() {
+			@Override
+			public void keyPressed(KeyEvent evt) {
+				if (evt.getKeyCode() == VK_ENTER) {
+					evt.consume();
+					termsAndConditionsCheckBox
+							.setSelected(!termsAndConditionsCheckBox
+									.isSelected());
+				}
+			}
+		});
+		// gbc.weightx = 0.0;
+		// gbc.weighty = 0.0;
+		// gbc.gridx = 0;
+		// gbc.gridy = 12;
+		// gbc.fill = NONE;
+		// gbc.anchor = WEST;
+		// gbc.gridwidth = 2;
+		// gbc.insets = new Insets(10, 10, 0, 0);
+		// mainPanel.add(termsAndConditionsCheckBox, gbc);
+
+		// Terms and conditions link
+		JEditorPane termsAndConditionsURL = new JEditorPane();
+		termsAndConditionsURL.setEditable(false);
+		termsAndConditionsURL.setBackground(getBackground());
+		termsAndConditionsURL.setFocusable(false);
+		HTMLEditorKit kit = new HTMLEditorKit();
+		termsAndConditionsURL.setEditorKit(kit);
+		StyleSheet styleSheet = kit.getStyleSheet();
+		// styleSheet.addRule("body {font-family:"+baseFont.getFamily()+"; font-size:"+baseFont.getSize()+";}");
+		// // base font looks bigger when rendered as HTML
+		styleSheet.addRule("body {font-family:" + baseFont.getFamily()
+				+ "; font-size:9px;}");
+		Document doc = kit.createDefaultDocument();
+		termsAndConditionsURL.setDocument(doc);
+		termsAndConditionsURL.setText("<html><body><a href=\""
+				+ TERMS_AND_CONDITIONS_URL + "\">" + TERMS_AND_CONDITIONS_URL
+				+ "</a></body></html>");
+		termsAndConditionsURL.addHyperlinkListener(new HyperlinkListener() {
+			@Override
+			public void hyperlinkUpdate(HyperlinkEvent he) {
+				if (he.getEventType() == ACTIVATED)
+					followHyperlinkToTandCs();
+			}
+		});
+		gbc.weightx = 0.0;
+		gbc.weighty = 0.0;
+		gbc.gridx = 0;
+		gbc.gridy = 13;
+		gbc.fill = NONE;
+		gbc.anchor = WEST;
+		gbc.gridwidth = 2;
+		gbc.insets = new Insets(5, 10, 0, 10);
+		JPanel termsAndConditionsPanel = new JPanel(new FlowLayout(LEFT));
+		termsAndConditionsPanel.add(termsAndConditionsCheckBox);
+		termsAndConditionsPanel.add(termsAndConditionsURL);
+		mainPanel.add(termsAndConditionsPanel, gbc);
+
+		// Button panel
+		JPanel buttonPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
+		JButton registerButton = new JButton("Register");
+		registerButton.setFont(baseFont);
+		registerButton.addKeyListener(new KeyAdapter() {
+			@Override
+			public void keyPressed(KeyEvent evt) {
+				if (evt.getKeyCode() == VK_ENTER) {
+					evt.consume();
+					register();
+				}
+			}
+		});
+		registerButton.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				register();
+			}
+		});
+		JButton doNotRegisterButton = new JButton("Do not ask me again");
+		doNotRegisterButton.setFont(baseFont);
+		doNotRegisterButton.addKeyListener(new KeyAdapter() {
+			@Override
+			public void keyPressed(KeyEvent evt) {
+				if (evt.getKeyCode() == VK_ENTER) {
+					evt.consume();
+					doNotRegister();
+				}
+			}
+		});
+		doNotRegisterButton.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				doNotRegister();
+			}
+		});
+		JButton remindMeLaterButton = new JButton("Remind me later"); // in 2 weeks
+		remindMeLaterButton.setFont(baseFont);
+		remindMeLaterButton.addKeyListener(new KeyAdapter() {
+			@Override
+			public void keyPressed(KeyEvent evt) {
+				if (evt.getKeyCode() == VK_ENTER) {
+					evt.consume();
+					remindMeLater();
+				}
+			}
+		});
+		remindMeLaterButton.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				remindMeLater();
+			}
+		});
+		buttonPanel.add(registerButton);
+		buttonPanel.add(remindMeLaterButton);
+		buttonPanel.add(doNotRegisterButton);
+		addDivider(buttonPanel, TOP, true);
+		gbc.gridx = 0;
+		gbc.gridy = 14;
+		gbc.fill = HORIZONTAL;
+		gbc.anchor = GridBagConstraints.CENTER;
+		gbc.insets = new Insets(5, 10, 0, 10);
+		gbc.gridwidth = 2;
+		mainPanel.add(buttonPanel, gbc);
+
+		getContentPane().setLayout(new BorderLayout());
+		getContentPane().add(mainPanel, CENTER);
+
+		pack();
+		setResizable(false);
+		// Center the dialog on the screen (we do not have the parent)
+		Dimension dimension = getToolkit().getScreenSize();
+		Rectangle abounds = getBounds();
+		setLocation((dimension.width - abounds.width) / 2,
+				(dimension.height - abounds.height) / 2);
+		setSize(getPreferredSize());
+	}
+
+	protected void remindMeLater() {
+		try {
+			FileUtils.touch(remindMeLaterFile);
+		} catch (IOException ioex) {
+			logger.error(
+					"Failed to touch the 'Remind me later' file at user registration.",
+					ioex);
+		}
+		closeDialog();
+	}
+
+	protected void doNotRegister() {
+		try {
+			FileUtils.touch(doNotRegisterMeFile);
+			if (remindMeLaterFile.exists())
+				remindMeLaterFile.delete();
+		} catch (IOException ioex) {
+			logger.error(
+					"Failed to touch the 'Do not register me' file at user registration.",
+					ioex);
+		}
+		closeDialog();
+	}
+
+	private void register() {
+		if (!validateForm())
+			return;
+		UserRegistrationData regData = new UserRegistrationData();
+		regData.setTavernaVersion(appName);
+		regData.setFirstName(firstNameTextField.getText());
+		regData.setLastName(lastNameTextField.getText());
+		regData.setEmailAddress(emailTextField.getText());
+		regData.setKeepMeInformed(keepMeInformedCheckBox.isSelected());
+		regData.setInstitutionOrCompanyName(institutionOrCompanyTextField
+				.getText());
+		regData.setIndustry(industryTypeTextField.getSelectedItem().toString());
+		regData.setField(fieldTextField.getText());
+		regData.setPurposeOfUsingTaverna(purposeTextArea.getText());
+
+		if (postUserRegistrationDataToServer(regData)) {
+			saveUserRegistrationData(regData, registrationDataFile);
+			if (remindMeLaterFile.exists())
+				remindMeLaterFile.delete();
+			closeDialog();
+		}
+	}
+
+	private boolean validateForm() {
+		String errorMessage = "";
+		if (firstNameTextField.getText().isEmpty())
+			errorMessage += "Please provide your first name.<br>";
+		if (lastNameTextField.getText().isEmpty())
+			errorMessage += "Please provide your last name.<br>";
+		if (emailTextField.getText().isEmpty())
+			errorMessage += "Please provide your email address.<br>";
+		if (institutionOrCompanyTextField.getText().isEmpty())
+			errorMessage += "Please provide your institution or company name.";
+		if (!errorMessage.isEmpty()) {
+			showMessageDialog(this, new JLabel("<html><body>"
+					+ errorMessage + "</body></html>"), "Error in form",
+					ERROR_MESSAGE);
+			return false;
+		}
+		if (!termsAndConditionsCheckBox.isSelected()) {
+			showMessageDialog(this, new JLabel(
+					"You must agree to the terms and conditions."),
+					"Error in form", ERROR_MESSAGE);
+			return false;
+		}
+		return true;
+	}
+
+	public UserRegistrationData loadUserRegistrationData(File propertiesFile) {
+		UserRegistrationData regData = new UserRegistrationData();
+		Properties props = new Properties();
+
+		// Try to retrieve data from file
+		try {
+			props.load(new FileInputStream(propertiesFile));
+		} catch (IOException e) {
+			logger.error("Failed to load old user registration data from "
+					+ propertiesFile.getAbsolutePath(), e);
+			return null;
+		}
+		regData.setTavernaVersion(props
+				.getProperty(TAVERNA_VERSION_PROPERTY_NAME));
+		regData.setFirstName(props.getProperty(FIRST_NAME_PROPERTY_NAME));
+		regData.setLastName(props.getProperty(LAST_NAME_PROPERTY_NAME));
+		regData.setEmailAddress(props.getProperty(EMAIL_ADDRESS_PROPERTY_NAME));
+		regData.setKeepMeInformed(props.getProperty(
+				KEEP_ME_INFORMED_PROPERTY_NAME).equals(TRUE));
+		regData.setInstitutionOrCompanyName(props
+				.getProperty(INSTITUTION_OR_COMPANY_PROPERTY_NAME));
+		regData.setIndustry(props.getProperty(INDUSTRY_PROPERTY_NAME));
+		regData.setField(props.getProperty(FIELD_PROPERTY_NAME));
+		regData.setPurposeOfUsingTaverna(props
+				.getProperty(PURPOSE_PROPERTY_NAME));
+		return regData;
+	}
+
+	private void enc(StringBuilder buffer, String name, Object value)
+			throws UnsupportedEncodingException {
+		if (buffer.length() != 0)
+			buffer.append('&');
+		buffer.append(URLEncoder.encode(name, "UTF-8"));
+		buffer.append('=');
+		buffer.append(URLEncoder.encode(value.toString(), "UTF-8"));
+	}
+
+	/**
+	 * Post registration data to our server.
+	 */
+	private boolean postUserRegistrationDataToServer(
+			UserRegistrationData regData) {
+		StringBuilder parameters = new StringBuilder();
+
+		/*
+		 * The 'submit' parameter - to let the server-side script know we are
+		 * submitting the user's registration form - all other requests will be
+		 * silently ignored
+		 */
+		try {
+			// value does not matter
+			enc(parameters, TAVERNA_REGISTRATION_POST_PARAMETER_NAME, "submit");
+
+			enc(parameters, TAVERNA_VERSION_POST_PARAMETER_NAME,
+					regData.getTavernaVersion());
+			enc(parameters, FIRST_NAME_POST_PARAMETER_NAME,
+					regData.getFirstName());
+			enc(parameters, LAST_NAME_POST_PARAMETER_NAME,
+					regData.getLastName());
+			enc(parameters, EMAIL_ADDRESS_POST_PARAMETER_NAME,
+					regData.getEmailAddress());
+			enc(parameters, KEEP_ME_INFORMED_POST_PARAMETER_PROPERTY_NAME,
+					regData.getKeepMeInformed());
+			enc(parameters, INSTITUTION_OR_COMPANY_POST_PARAMETER_NAME,
+					regData.getInstitutionOrCompanyName());
+			enc(parameters, INDUSTRY_TYPE_POST_PARAMETER_NAME,
+					regData.getIndustry());
+			enc(parameters, FIELD_POST_PARAMETER_NAME, regData.getField());
+			enc(parameters, PURPOSE_POST_PARAMETER_NAME,
+					regData.getPurposeOfUsingTaverna());
+		} catch (UnsupportedEncodingException ueex) {
+			logger.error(FAILED + "Could not url encode post parameters", ueex);
+			showMessageDialog(null, REGISTRATION_FAILED_MSG,
+					"Error encoding registration data", ERROR_MESSAGE);
+			return false;
+		}
+		String server = REGISTRATION_URL;
+		logger.info("Posting user registartion to " + server
+				+ " with parameters: " + parameters);
+		String response = "";
+		String failure;
+		try {
+			URL url = new URL(server);
+			URLConnection conn = url.openConnection();
+			/*
+			 * Set timeout to e.g. 7 seconds, otherwise we might hang too long
+			 * if server is not responding and it will block Taverna
+			 */
+			conn.setConnectTimeout(7000);
+			// Set connection parameters
+			conn.setDoInput(true);
+			conn.setDoOutput(true);
+			conn.setUseCaches(false);
+			// Make server believe we are HTML form data...
+			conn.setRequestProperty("Content-Type",
+					"application/x-www-form-urlencoded");
+			// Write out the bytes of the content string to the stream.
+			try (DataOutputStream out = new DataOutputStream(
+					conn.getOutputStream())) {
+				out.writeBytes(parameters.toString());
+				out.flush();
+			}
+			// Read response from the input stream.
+			try (BufferedReader in = new BufferedReader(new InputStreamReader(
+					conn.getInputStream()))) {
+				String temp;
+				while ((temp = in.readLine()) != null)
+					response += temp + "\n";
+				// Remove the last \n character
+				if (!response.isEmpty())
+					response = response.substring(0, response.length() - 1);
+			}
+			if (response.equals("Registration successful!"))
+				return true;
+			logger.error(FAILED + "Response form server was: " + response);
+			failure = "Error saving registration data on the server";
+		} catch (ConnectException ceex) {
+			/*
+			 * the connection was refused remotely (e.g. no process is listening
+			 * on the remote address/port).
+			 */
+			logger.error(
+					FAILED
+							+ "Registration server is not listening of the specified url.",
+					ceex);
+			failure = "Registration server is not listening at the specified url";
+		} catch (SocketTimeoutException stex) {
+			// timeout has occurred on a socket read or accept.
+			logger.error(FAILED + "Socket timeout occurred.", stex);
+			failure = "Registration server timeout";
+		} catch (MalformedURLException muex) {
+			logger.error(FAILED + "Registartion server's url is malformed.",
+					muex);
+			failure = "Error with registration server's url";
+		} catch (IOException ioex) {
+			logger.error(
+					FAILED
+							+ "Failed to open url connection to registration server or writing/reading to/from it.",
+					ioex);
+			failure = "Error opening connection to the registration server";
+		}
+		showMessageDialog(null, REGISTRATION_FAILED_MSG, failure, ERROR_MESSAGE);
+		return false;
+	}
+
+	private void saveUserRegistrationData(UserRegistrationData regData,
+			File propertiesFile) {
+		Properties props = new Properties();
+		props.setProperty(TAVERNA_VERSION_PROPERTY_NAME,
+				regData.getTavernaVersion());
+		props.setProperty(FIRST_NAME_PROPERTY_NAME, regData.getFirstName());
+		props.setProperty(LAST_NAME_PROPERTY_NAME, regData.getLastName());
+		props.setProperty(EMAIL_ADDRESS_PROPERTY_NAME,
+				regData.getEmailAddress());
+		props.setProperty(KEEP_ME_INFORMED_PROPERTY_NAME,
+				regData.getKeepMeInformed() ? TRUE : FALSE);
+		props.setProperty(INSTITUTION_OR_COMPANY_PROPERTY_NAME,
+				regData.getInstitutionOrCompanyName());
+		props.setProperty(INDUSTRY_PROPERTY_NAME, regData.getIndustry());
+		props.setProperty(FIELD_PROPERTY_NAME,
+				regData.getPurposeOfUsingTaverna());
+		props.setProperty(PURPOSE_PROPERTY_NAME,
+				regData.getPurposeOfUsingTaverna());
+
+		// Write the properties file.
+		try {
+			props.store(new FileOutputStream(propertiesFile), null);
+		} catch (Exception e) {
+			logger.error("Failed to save user registration data locally on disk.");
+		}
+	}
+
+	private void closeDialog() {
+		setVisible(false);
+		dispose();
+	}
+
+	/**
+	 * Adds a light gray or etched border to the top or bottom of a JComponent.
+	 * 
+	 * @author David Withers
+	 * @param component
+	 */
+	protected void addDivider(JComponent component, final int position,
+			final boolean etched) {
+		component.setBorder(new Border() {
+			private final Color borderColor = new Color(.6f, .6f, .6f);
+
+			@Override
+			public Insets getBorderInsets(Component c) {
+				if (position == TOP)
+					return new Insets(5, 0, 0, 0);
+				else
+					return new Insets(0, 0, 5, 0);
+			}
+
+			@Override
+			public boolean isBorderOpaque() {
+				return false;
+			}
+
+			@Override
+			public void paintBorder(Component c, Graphics g, int x, int y,
+					int width, int height) {
+				if (position == TOP) {
+					if (etched) {
+						g.setColor(borderColor);
+						g.drawLine(x, y, x + width, y);
+						g.setColor(WHITE);
+						g.drawLine(x, y + 1, x + width, y + 1);
+					} else {
+						g.setColor(LIGHT_GRAY);
+						g.drawLine(x, y, x + width, y);
+					}
+				} else {
+					if (etched) {
+						g.setColor(borderColor);
+						g.drawLine(x, y + height - 2, x + width, y + height - 2);
+						g.setColor(WHITE);
+						g.drawLine(x, y + height - 1, x + width, y + height - 1);
+					} else {
+						g.setColor(LIGHT_GRAY);
+						g.drawLine(x, y + height - 1, x + width, y + height - 1);
+					}
+				}
+			}
+		});
+	}
+
+	private void followHyperlinkToTandCs() {
+		// Open a Web browser
+		try {
+			Desktop.getDesktop().browse(new URI(TERMS_AND_CONDITIONS_URL));
+		} catch (Exception ex) {
+			logger.error("User registration: Failed to launch browser to show terms and conditions at "
+					+ TERMS_AND_CONDITIONS_URL);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/UserRegistrationHook.java
----------------------------------------------------------------------
diff --git a/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/UserRegistrationHook.java b/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/UserRegistrationHook.java
new file mode 100644
index 0000000..257c3f3
--- /dev/null
+++ b/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/UserRegistrationHook.java
@@ -0,0 +1,163 @@
+/*******************************************************************************
+ * Copyright (C) 2009-2010 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.impl;
+
+import static java.awt.GraphicsEnvironment.isHeadless;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.Date;
+
+import net.sf.taverna.t2.workbench.StartupSPI;
+import uk.org.taverna.configuration.app.ApplicationConfiguration;
+
+public class UserRegistrationHook implements StartupSPI {
+	/** Delay between when we ask the user about registration, in milliseconds */
+	private static final int TWO_WEEKS = 14 * 24 * 3600 * 1000;
+	public static final String REGISTRATION_DIRECTORY_NAME = "registration";
+	public static final String REGISTRATION_DATA_FILE_NAME = "registration_data.properties";
+	public static final String REMIND_ME_LATER_FILE_NAME = "remind_me_later";
+	public static final String DO_NOT_REGISTER_ME_FILE_NAME = "do_not_register_me";
+
+	private ApplicationConfiguration applicationConfiguration;
+
+	@Override
+	public int positionHint() {
+		return 50;
+	}
+
+	@Override
+	public boolean startup() {
+		File registrationDirectory = getRegistrationDirectory();
+		File registrationDataFile = new File(registrationDirectory,
+				REGISTRATION_DATA_FILE_NAME);
+		File doNotRegisterMeFile = new File(registrationDirectory,
+				DO_NOT_REGISTER_ME_FILE_NAME);
+		File remindMeLaterFile = new File(registrationDirectory,
+				REMIND_ME_LATER_FILE_NAME);
+
+		// if we are running headlessly just return
+		if (isHeadless())
+			return true;
+		// For Taverna snapshots - do not ask user to register
+		if (applicationConfiguration.getName().toLowerCase().contains("snapshot"))
+			return true;
+
+		// If there is already user's registration data present - exit.
+		if (registrationDataFile.exists())
+			return true;
+
+		// If user did not want to register - exit.
+		if (doNotRegisterMeFile.exists())
+			return true;
+
+		/*
+		 * If user said to remind them - check if more than 2 weeks passed since
+		 * we asked previously.
+		 */
+		if (remindMeLaterFile.exists()) {
+			long lastModified = remindMeLaterFile.lastModified();
+			long now = new Date().getTime();
+			if (now - lastModified < TWO_WEEKS)
+				// 2 weeks have not passed since we last asked
+				return true;
+
+			// Ask user again if they want to register
+			UserRegistrationForm form = new UserRegistrationForm(
+					applicationConfiguration.getName(), registrationDataFile,
+					doNotRegisterMeFile, remindMeLaterFile);
+			form.setVisible(true);
+			return true;
+		}
+
+		/*
+		 * Check if there are previous Taverna versions installed and find the
+		 * latest one that contains user registration data, if any. Ask user if
+		 * they want to upload that previous data.
+		 */
+		final File appHomeDirectory = applicationConfiguration.getApplicationHomeDir();
+		File parentDirectory = appHomeDirectory.getParentFile();
+		FileFilter fileFilter = new FileFilter() {
+			@Override
+			public boolean accept(File file) {
+				return !(file.getName().equals(appHomeDirectory.getName())
+						// Exclude Taverna home directory for this app
+						&& file.isDirectory()
+						&& file.getName().toLowerCase().startsWith("taverna-")
+						// exclude snapshots
+						&& !file.getName().toLowerCase().contains("snapshot")
+						// exclude command line tool
+						&& !file.getName().toLowerCase().contains("cmd")
+						// exclude dataviewer
+						&& !file.getName().toLowerCase().contains("dataviewer"));
+			}
+		};
+		File[] tavernaDirectories = parentDirectory.listFiles(fileFilter);
+		// Find the latest previous registration data file, if any
+		File previousRegistrationDataFile = null;
+		for (File tavernaDirectory : tavernaDirectories) {
+			File regFile = new File(tavernaDirectory, REGISTRATION_DIRECTORY_NAME
+					+ System.getProperty("file.separator") + REGISTRATION_DATA_FILE_NAME);
+			if (!regFile.exists())
+				continue;
+			if (previousRegistrationDataFile == null)
+				previousRegistrationDataFile = regFile;
+			else if (previousRegistrationDataFile.lastModified() < regFile
+					.lastModified())
+				previousRegistrationDataFile = regFile;
+		}
+
+		UserRegistrationForm form;
+		if (previousRegistrationDataFile == null)
+			// No previous registration file - ask user to register
+			form = new UserRegistrationForm(applicationConfiguration.getName(),
+					registrationDataFile, doNotRegisterMeFile,
+					remindMeLaterFile);
+		else
+			/*
+			 * Fill in user's old registration data in the form and ask them to
+			 * register
+			 */
+			form = new UserRegistrationForm(applicationConfiguration.getName(),
+					previousRegistrationDataFile, registrationDataFile,
+					doNotRegisterMeFile, remindMeLaterFile);
+		form.setVisible(true);
+		return true;
+	}
+
+	/**
+	 * Gets the registration directory where info about registration will be
+	 * saved to.
+	 */
+	public File getRegistrationDirectory() {
+		File home = applicationConfiguration.getApplicationHomeDir();
+
+		File registrationDirectory = new File(home, REGISTRATION_DIRECTORY_NAME);
+		if (!registrationDirectory.exists())
+			registrationDirectory.mkdir();
+		return registrationDirectory;
+	}
+
+	public void setApplicationConfiguration(
+			ApplicationConfiguration applicationConfiguration) {
+		this.applicationConfiguration = applicationConfiguration;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/72850d5a/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/WorkbenchImpl.java
----------------------------------------------------------------------
diff --git a/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/WorkbenchImpl.java b/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/WorkbenchImpl.java
new file mode 100644
index 0000000..16f189e
--- /dev/null
+++ b/taverna-workbench-workbench-impl/src/main/java/net/sf/taverna/t2/workbench/ui/impl/WorkbenchImpl.java
@@ -0,0 +1,538 @@
+/*******************************************************************************
+ * Copyright (C) 2007-2010 The University of Manchester
+ *
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ *
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.impl;
+
+import static java.awt.GridBagConstraints.BOTH;
+import static java.awt.GridBagConstraints.CENTER;
+import static java.awt.GridBagConstraints.HORIZONTAL;
+import static java.awt.GridBagConstraints.LINE_START;
+import static java.lang.Thread.setDefaultUncaughtExceptionHandler;
+import static java.util.prefs.Preferences.userNodeForPackage;
+import static javax.swing.JOptionPane.ERROR_MESSAGE;
+import static javax.swing.JOptionPane.WARNING_MESSAGE;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static javax.swing.SwingUtilities.invokeLater;
+import static javax.swing.UIManager.getCrossPlatformLookAndFeelClassName;
+import static javax.swing.UIManager.getLookAndFeel;
+import static javax.swing.UIManager.getLookAndFeelDefaults;
+import static javax.swing.UIManager.getSystemLookAndFeelClassName;
+import static net.sf.taverna.t2.workbench.MainWindow.setMainWindow;
+import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.errorMessageIcon;
+import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.infoMessageIcon;
+import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.questionMessageIcon;
+import static net.sf.taverna.t2.workbench.icons.WorkbenchIcons.warningMessageIcon;
+import static org.apache.log4j.Logger.getLogger;
+
+import java.awt.CardLayout;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.File;
+import java.io.IOException;
+import java.lang.Thread.UncaughtExceptionHandler;
+import java.net.URL;
+import java.util.List;
+import java.util.Map;
+import java.util.prefs.Preferences;
+
+import javax.swing.ImageIcon;
+import javax.swing.JFrame;
+import javax.swing.JMenuBar;
+import javax.swing.JPanel;
+import javax.swing.JToolBar;
+import javax.swing.UIManager;
+
+import net.sf.taverna.t2.lang.observer.Observable;
+import net.sf.taverna.t2.lang.observer.SwingAwareObserver;
+import net.sf.taverna.t2.ui.menu.MenuManager;
+import net.sf.taverna.t2.ui.menu.MenuManager.MenuManagerEvent;
+import net.sf.taverna.t2.ui.menu.MenuManager.UpdatedMenuManagerEvent;
+import net.sf.taverna.t2.workbench.ShutdownSPI;
+import net.sf.taverna.t2.workbench.StartupSPI;
+import net.sf.taverna.t2.workbench.configuration.workbench.WorkbenchConfiguration;
+import net.sf.taverna.t2.workbench.configuration.workbench.ui.T2ConfigurationFrame;
+import net.sf.taverna.t2.workbench.edits.EditManager;
+import net.sf.taverna.t2.workbench.file.FileManager;
+import net.sf.taverna.t2.workbench.file.exceptions.OpenException;
+import net.sf.taverna.t2.workbench.helper.Helper;
+import net.sf.taverna.t2.workbench.selection.SelectionManager;
+import net.sf.taverna.t2.workbench.ui.Workbench;
+import net.sf.taverna.t2.workbench.ui.zaria.PerspectiveSPI;
+
+import org.apache.log4j.Logger;
+import org.simplericity.macify.eawt.Application;
+import org.simplericity.macify.eawt.ApplicationAdapter;
+import org.simplericity.macify.eawt.ApplicationEvent;
+import org.simplericity.macify.eawt.ApplicationListener;
+import org.simplericity.macify.eawt.DefaultApplication;
+
+import uk.org.taverna.commons.plugin.PluginException;
+import uk.org.taverna.commons.plugin.PluginManager;
+import uk.org.taverna.configuration.app.ApplicationConfiguration;
+
+/**
+ * The main workbench frame.
+ *
+ * @author David Withers
+ * @author Stian Soiland-Reyes
+ */
+public class WorkbenchImpl extends JFrame implements Workbench {
+	private static final String NIMBUS = "com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel";
+	private static final String LAUNCHER_LOGO_PNG = "/launcher_logo.png";
+	private static final long serialVersionUID = 1L;
+	private static Logger logger = getLogger(WorkbenchImpl.class);
+	private static Preferences userPreferences = userNodeForPackage(WorkbenchImpl.class);
+	
+	private Application osxApp = new DefaultApplication();
+	private ApplicationListener osxAppListener = new OSXAppListener();
+	private MenuManager menuManager;
+	private FileManager fileManager;
+	@SuppressWarnings("unused")
+	private EditManager editManager;
+	private PluginManager pluginManager;
+	private SelectionManager selectionManager;
+	private WorkbenchConfiguration workbenchConfiguration;
+	private ApplicationConfiguration applicationConfiguration;
+	private WorkbenchPerspectives workbenchPerspectives;
+	private T2ConfigurationFrame t2ConfigurationFrame;
+	private JToolBar perspectiveToolBar;
+	private List<StartupSPI> startupHooks;
+	private List<ShutdownSPI> shutdownHooks;
+	private final List<PerspectiveSPI> perspectives;
+	private JMenuBar menuBar;
+	private JToolBar toolBar;
+	private MenuManagerObserver menuManagerObserver;
+
+	public WorkbenchImpl(List<StartupSPI> startupHooks,
+			List<ShutdownSPI> shutdownHooks, List<PerspectiveSPI> perspectives) {
+		this.perspectives = perspectives;
+		this.startupHooks = startupHooks;
+		this.shutdownHooks = shutdownHooks;
+		setMainWindow(this);
+	}
+
+	protected void initialize() {
+		setExceptionHandler();
+		setLookAndFeel();
+
+		// Set icons for Error, Information, Question and Warning messages
+		UIManager.put("OptionPane.errorIcon", errorMessageIcon);
+		UIManager.put("OptionPane.informationIcon", infoMessageIcon);
+		UIManager.put("OptionPane.questionIcon", questionMessageIcon);
+		UIManager.put("OptionPane.warningIcon", warningMessageIcon);
+
+		// Call the startup hooks
+		if (!callStartupHooks()) {
+			System.exit(0);
+		}
+
+		makeGUI();
+		fileManager.newDataflow();
+		try {
+			pluginManager.loadPlugins();
+		} catch (PluginException e) {
+			// TODO Auto-generated catch block
+			e.printStackTrace();
+		}
+
+		/*
+		 * the DataflowEditsListener changes the WorkflowBundle ID for every
+		 * workflow edit and changes the URI so port definitions can't find the
+		 * port they refer to
+		 */
+		// TODO check if it's OK to not update the WorkflowBundle ID
+		//editManager.addObserver(new DataflowEditsListener());
+
+		closeTheSplashScreen();
+		setVisible(true);
+	}
+
+	private void closeTheSplashScreen() {
+//		SplashScreen splash = SplashScreen.getSplashScreen();
+//		if (splash != null) {
+//			splash.setClosable();
+//			splash.requestClose();
+//		}
+	}
+
+	private void showAboutDialog() {
+		// TODO implement this!
+	}
+
+	private void makeGUI() {
+		setLayout(new GridBagLayout());
+
+		addWindowListener(new WindowClosingListener());
+		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
+
+		Helper.setKeyCatcher(this);
+
+		URL launcherLogo = getClass().getResource(LAUNCHER_LOGO_PNG);
+		if (launcherLogo != null) {
+			ImageIcon imageIcon = new ImageIcon(launcherLogo);
+			setIconImage(imageIcon.getImage());
+		}
+		setTitle(applicationConfiguration.getTitle());
+
+		osxApp.setEnabledPreferencesMenu(true);
+		osxApp.setEnabledAboutMenu(true);
+		osxApp.addApplicationListener(osxAppListener);
+
+		/*
+		 * Set the size and position of the Workbench to the last saved values
+		 * or use the default ones the first time it is launched
+		 */
+		loadSizeAndLocationPrefs();
+
+		GridBagConstraints gbc = new GridBagConstraints();
+		gbc.gridx = 0;
+		gbc.gridy = 0;
+		gbc.weightx = 0.1;
+		gbc.fill = HORIZONTAL;
+		gbc.anchor = LINE_START;
+
+		add(makeToolbarPanel(), gbc);
+
+		gbc.anchor = CENTER;
+		gbc.fill = BOTH;
+		gbc.gridy = 1;
+		gbc.weightx = 0.1;
+		gbc.weighty = 0.1;
+
+		add(makePerspectivePanel(), gbc);
+
+		menuBar = menuManager.createMenuBar();
+		setJMenuBar(menuBar);
+	}
+
+	protected JPanel makeToolbarPanel() {
+		JPanel toolbarPanel = new JPanel(new GridBagLayout());
+
+		GridBagConstraints gbc = new GridBagConstraints();
+		gbc.gridx = 0;
+		gbc.gridy = 0;
+		gbc.gridwidth = 2;
+		gbc.anchor = LINE_START;
+
+		toolBar = menuManager.createToolBar();
+		toolBar.setFloatable(false);
+		toolbarPanel.add(toolBar, gbc);
+
+		perspectiveToolBar = new JToolBar("Perspectives");
+		perspectiveToolBar.setFloatable(false);
+		gbc.gridy = 1;
+		gbc.weightx = 0.1;
+		gbc.fill = HORIZONTAL;
+		toolbarPanel.add(perspectiveToolBar, gbc);
+
+		return toolbarPanel;
+	}
+
+	private JPanel makePerspectivePanel() {
+		CardLayout perspectiveLayout = new CardLayout();
+		JPanel perspectivePanel = new JPanel(perspectiveLayout);
+		workbenchPerspectives = new WorkbenchPerspectives(perspectiveToolBar,
+				perspectivePanel, perspectiveLayout, selectionManager);
+		workbenchPerspectives.setPerspectives(perspectives);
+		return perspectivePanel;
+	}
+
+	@Override
+	public void makeNamedComponentVisible(String componentName) {
+		// basePane.makeNamedComponentVisible(componentName);
+	}
+
+	protected void setExceptionHandler() {
+		setDefaultUncaughtExceptionHandler(new ExceptionHandler());
+	}
+
+	public void setStartupHooks(List<StartupSPI> startupHooks) {
+		this.startupHooks = startupHooks;
+	}
+
+	/**
+	 * Calls the startup methods on all the {@link StartupSPI}s. If any startup
+	 * method returns <code>false</code> (meaning that the Workbench will not
+	 * function at all) then this method returns <code>false</code>.
+	 */
+	private boolean callStartupHooks() {
+		for (StartupSPI startupSPI : startupHooks)
+			if (!startupSPI.startup())
+				return false;
+		return true;
+	}
+
+	@Override
+	public void exit() {
+		if (callShutdownHooks())
+			System.exit(0);
+	}
+
+	public void setShutdownHooks(List<ShutdownSPI> shutdownHooks) {
+		this.shutdownHooks = shutdownHooks;
+	}
+
+	/**
+	 * Calls all the shutdown on all the {@link ShutdownSPI}s. If a shutdown
+	 * returns <code>false</code> (meaning that the shutdown process should be
+	 * aborted) then this method returns with a value of <code>false</code>
+	 * immediately.
+	 *
+	 * @return <code>true</code> if all the <code>ShutdownSPIs</code> return
+	 *         <code>true</code> and the workbench shutdown should proceed
+	 */
+	private boolean callShutdownHooks() {
+		for (ShutdownSPI shutdownSPI : shutdownHooks)
+			if (!shutdownSPI.shutdown())
+				return false;
+		return true;
+	}
+
+	/**
+	 * Store current Workbench position and size.
+	 */
+	@Override
+	public void storeSizeAndLocationPrefs() throws IOException {
+		userPreferences.putInt("width", getWidth());
+		userPreferences.putInt("height", getHeight());
+		userPreferences.putInt("x", getX());
+		userPreferences.putInt("y", getY());
+	}
+
+	/**
+	 * Loads last saved Workbench position and size.
+	 */
+	private void loadSizeAndLocationPrefs() {
+		Dimension screen = getToolkit().getScreenSize();
+
+		int width = userPreferences.getInt("width", (int) (screen.getWidth() * 0.75));
+		int height = userPreferences.getInt("height", (int) (screen.getHeight() * 0.75));
+		int x = userPreferences.getInt("x", 0);
+		int y = userPreferences.getInt("y", 0);
+
+		// Make sure our window is not too big
+		width = Math.min((int) screen.getWidth(), width);
+		height = Math.min((int) screen.getHeight(), height);
+
+		// Move to upper left corner if we are too far off
+		if (x > (screen.getWidth() - 50) || x < 0)
+			x = 0;
+		if (y > (screen.getHeight() - 50) || y < 0)
+			y = 0;
+
+		this.setSize(width, height);
+		this.setLocation(x, y);
+	}
+
+	public static void setLookAndFeel() {
+		String defaultLaf = System.getProperty("swing.defaultlaf");
+		try {
+			if (defaultLaf != null) {
+				UIManager.setLookAndFeel(defaultLaf);
+				return;
+			}
+		} catch (Exception e) {
+			logger.info("Can't set requested look and feel -Dswing.defaultlaf="
+					+ defaultLaf, e);
+		}
+		String os = System.getProperty("os.name");
+		if (os.contains("Mac") || os.contains("Windows")) {
+			// For OSX and Windows use the system look and feel
+			String systemLF = getSystemLookAndFeelClassName();
+			try {
+				UIManager.setLookAndFeel(systemLF);
+				getLookAndFeelDefaults().put("ClassLoader",
+						WorkbenchImpl.class.getClassLoader());
+				logger.info("Using system L&F " + systemLF);
+				return;
+			} catch (Exception ex2) {
+				logger.error("Unable to load system look and feel " + systemLF,
+						ex2);
+			}
+		}
+		/*
+		 * The system look and feel on *NIX
+		 * (com.sun.java.swing.plaf.gtk.GTKLookAndFeel) looks like Windows 3.1..
+		 * try to use Nimbus (Java 6e10 and later)
+		 */
+		try {
+			UIManager.setLookAndFeel(NIMBUS);
+			logger.info("Using Nimbus look and feel");
+			return;
+		} catch (Exception e) {
+		}
+
+		// Metal should be better than GTK still
+		try {
+			String crossPlatform = getCrossPlatformLookAndFeelClassName();
+			UIManager.setLookAndFeel(crossPlatform);
+			logger.info("Using cross platform Look and Feel " + crossPlatform);
+			return;
+		} catch (Exception e){
+		}
+
+		// Final fallback
+		try {
+			String systemLF = getSystemLookAndFeelClassName();
+			UIManager.setLookAndFeel(systemLF);
+			logger.info("Using system platform Look and Feel " + systemLF);
+		} catch (Exception e){
+			logger.info("Using default Look and Feel " + getLookAndFeel());
+		}
+	}
+
+	public void setMenuManager(MenuManager menuManager) {
+		if (this.menuManager != null && menuManagerObserver != null)
+			this.menuManager.removeObserver(menuManagerObserver);
+		this.menuManager = menuManager;
+		menuManagerObserver = new MenuManagerObserver();
+		menuManager.addObserver(menuManagerObserver);
+	}
+
+	public void setFileManager(FileManager fileManager) {
+		this.fileManager = fileManager;
+	}
+
+	public void setEditManager(EditManager editManager) {
+		this.editManager = editManager;
+	}
+
+	public void refreshPerspectives(Object service, Map<?,?> properties) {
+		workbenchPerspectives.refreshPerspectives();
+	}
+
+	public void setWorkbenchConfiguration(WorkbenchConfiguration workbenchConfiguration) {
+		this.workbenchConfiguration = workbenchConfiguration;
+	}
+
+	public void setApplicationConfiguration(ApplicationConfiguration applicationConfiguration) {
+		this.applicationConfiguration = applicationConfiguration;
+	}
+
+	public void setT2ConfigurationFrame(T2ConfigurationFrame t2ConfigurationFrame) {
+		this.t2ConfigurationFrame = t2ConfigurationFrame;
+	}
+
+	public void setSelectionManager(SelectionManager selectionManager) {
+		this.selectionManager = selectionManager;
+	}
+
+	public void setPluginManager(PluginManager pluginManager) {
+		this.pluginManager = pluginManager;
+	}
+
+	private final class MenuManagerObserver extends
+			SwingAwareObserver<MenuManagerEvent> {
+		@Override
+		public void notifySwing(Observable<MenuManagerEvent> sender,
+				MenuManagerEvent message) {
+			if (message instanceof UpdatedMenuManagerEvent
+					&& WorkbenchImpl.this.isVisible())
+				refreshMenus();
+		}
+	}
+	
+	private void refreshMenus() {
+		if (menuBar != null) {
+			menuBar.revalidate();
+			menuBar.repaint();
+		}
+		if (toolBar != null) {
+			toolBar.revalidate();
+			toolBar.repaint();
+		}
+	}
+
+	private final class ExceptionHandler implements UncaughtExceptionHandler {
+		@Override
+		public void uncaughtException(Thread t, Throwable e) {
+			logger.error("Uncaught exception in " + t, e);
+			if (e instanceof Exception
+					&& !workbenchConfiguration.getWarnInternalErrors()) {
+				/*
+				 * User preference disables warnings - but we'll show it anyway
+				 * if it is an Error (which is more serious)
+				 */
+				return;
+			}
+			final String message;
+			final String title;
+			final int style;
+			if (t.getClass().getName().equals("java.awt.EventDispatchThread")) {
+				message = "The user action could not be completed due to an unexpected error:\n"
+						+ e;
+				title = "Could not complete user action";
+				style = ERROR_MESSAGE;
+			} else {
+				message = "An unexpected internal error occured in \n" + t + ":\n" + e;
+				title = "Unexpected internal error";
+				style = WARNING_MESSAGE;
+			}
+			invokeLater(new Runnable() {
+				@Override
+				public void run() {
+					showMessageDialog(WorkbenchImpl.this, message, title, style);
+				}
+			});
+		}
+	}
+
+	private class WindowClosingListener extends WindowAdapter {
+		@Override
+		public void windowClosing(WindowEvent e) {
+			exit();
+		}
+	}
+
+	private class OSXAppListener extends ApplicationAdapter {
+		@Override
+		public void handleAbout(ApplicationEvent e) {
+			showAboutDialog();
+			e.setHandled(true);
+		}
+
+		@Override
+		public void handleQuit(ApplicationEvent e) {
+			e.setHandled(true);
+			exit();
+		}
+
+		@Override
+		public void handlePreferences(ApplicationEvent e) {
+			e.setHandled(true);
+			t2ConfigurationFrame.showFrame();
+		}
+
+		@Override
+		public void handleOpenFile(ApplicationEvent e) {
+			try {
+				if (e.getFilename() != null) {
+					fileManager.openDataflow(null, new File(e.getFilename()));
+					e.setHandled(true);
+				}
+			} catch (OpenException | IllegalStateException ex) {
+				logger.warn("Could not open file " + e.getFilename(), ex);
+			}
+		}
+	}
+}