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/23 11:22:46 UTC

[23/51] [partial] incubator-taverna-workbench git commit: Revert "temporarily empty repository"

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/8c4b365e/taverna-workbench-httpproxy-config/src/main/java/net/sf/taverna/t2/workbench/httpproxy/config/HttpProxyConfigurationPanel.java
----------------------------------------------------------------------
diff --git a/taverna-workbench-httpproxy-config/src/main/java/net/sf/taverna/t2/workbench/httpproxy/config/HttpProxyConfigurationPanel.java b/taverna-workbench-httpproxy-config/src/main/java/net/sf/taverna/t2/workbench/httpproxy/config/HttpProxyConfigurationPanel.java
new file mode 100644
index 0000000..1229d57
--- /dev/null
+++ b/taverna-workbench-httpproxy-config/src/main/java/net/sf/taverna/t2/workbench/httpproxy/config/HttpProxyConfigurationPanel.java
@@ -0,0 +1,582 @@
+/*******************************************************************************
+ * 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.httpproxy.config;
+
+import static java.awt.GridBagConstraints.BOTH;
+import static java.awt.GridBagConstraints.CENTER;
+import static java.awt.GridBagConstraints.HORIZONTAL;
+import static java.awt.GridBagConstraints.NONE;
+import static java.awt.GridBagConstraints.WEST;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED;
+import static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED;
+import static net.sf.taverna.t2.workbench.helper.Helper.showHelp;
+import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.PROXY_USE_OPTION;
+import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.SYSTEM_NON_PROXY_HOSTS;
+import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.SYSTEM_PROXY_HOST;
+import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.SYSTEM_PROXY_PASSWORD;
+import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.SYSTEM_PROXY_PORT;
+import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.SYSTEM_PROXY_USER;
+import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.TAVERNA_NON_PROXY_HOSTS;
+import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.TAVERNA_PROXY_HOST;
+import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.TAVERNA_PROXY_PASSWORD;
+import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.TAVERNA_PROXY_PORT;
+import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.TAVERNA_PROXY_USER;
+import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.USE_NO_PROXY_OPTION;
+import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.USE_SPECIFIED_VALUES_OPTION;
+import static uk.org.taverna.configuration.proxy.HttpProxyConfiguration.USE_SYSTEM_PROPERTIES_OPTION;
+
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.AbstractAction;
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JScrollPane;
+import javax.swing.JTextArea;
+import javax.swing.JTextField;
+import javax.swing.border.EmptyBorder;
+
+import net.sf.taverna.t2.lang.ui.DialogTextArea;
+import uk.org.taverna.configuration.proxy.HttpProxyConfiguration;
+
+/**
+ * The HttpProxyConfigurationPanel provides the user interface to a
+ * {@link HttpProxyConfiguration} to determine how HTTP Connections are made by
+ * Taverna.
+ * 
+ * @author alanrw
+ * @author David Withers
+ */
+public class HttpProxyConfigurationPanel extends JPanel {
+	static final long serialVersionUID = 3668473431971125038L;
+	/**
+	 * The size of the field for the JTextFields.
+	 */
+	private static int TEXTFIELD_SIZE = 25;
+
+	private final HttpProxyConfiguration httpProxyConfiguration;
+	/**
+	 * RadioButtons that are in a common ButtonGroup. Selecting one of them
+	 * indicates whether the system http proxy settings, the ad hoc specified
+	 * values or no proxy settings at all should be used.
+	 */
+	private JRadioButton useSystemProperties;
+	private JRadioButton useSpecifiedValues;
+	private JRadioButton useNoProxy;
+	/**
+	 * JTextFields and one DialogTextArea to hold the settings for the HTTP
+	 * proxy properties. The values are only editable if the user picks
+	 * useSpecifiedValues.
+	 */
+	private JTextField proxyHostField;
+	private JTextField proxyPortField;
+	private JTextField proxyUserField;
+	private JTextField proxyPasswordField;
+	private DialogTextArea nonProxyHostsArea;
+	private JScrollPane nonProxyScrollPane;
+	/**
+	 * A string that indicates which HTTP setting option the user has currently
+	 * picked. This does not necesarily match that which has been applied.
+	 */
+	private String shownOption = USE_SYSTEM_PROPERTIES_OPTION;
+
+	/**
+	 * The HttpProxyConfigurationPanel consists of a set of properties where the
+	 * configuration values for HTTP can be specified and a set of buttons where
+	 * the more general apply, help etc. appear.
+	 */
+	public HttpProxyConfigurationPanel(
+			HttpProxyConfiguration httpProxyConfiguration) {
+		this.httpProxyConfiguration = httpProxyConfiguration;
+		initComponents();
+	}
+
+	/**
+	 * Populates the panel with a representation of the current HTTP proxy
+	 * settings for the specified {@link HttpProxyConfiguration} and also the
+	 * capability to alter them.
+	 */
+	private void initComponents() {
+		shownOption = httpProxyConfiguration.getProperty(PROXY_USE_OPTION);
+
+		this.setLayout(new GridBagLayout());
+
+		GridBagConstraints gbc = new GridBagConstraints();
+
+		// Title describing what kind of settings we are configuring here
+		JTextArea descriptionText = new JTextArea("HTTP proxy configuration");
+		descriptionText.setLineWrap(true);
+		descriptionText.setWrapStyleWord(true);
+		descriptionText.setEditable(false);
+		descriptionText.setFocusable(false);
+		descriptionText.setBorder(new EmptyBorder(10, 10, 10, 10));
+		gbc.anchor = WEST;
+		gbc.gridx = 0;
+		gbc.gridy = 0;
+		gbc.gridwidth = 2;
+		gbc.weightx = 1.0;
+		gbc.weighty = 0.0;
+		gbc.fill = HORIZONTAL;
+		this.add(descriptionText, gbc);
+
+		/**
+		 * Generate the three radio buttons and put them in a group. Each button
+		 * is bound to an action that alters the shownOption and re-populates
+		 * the shown HTTP property fields.
+		 */
+		useNoProxy = new JRadioButton("Do not use a proxy");
+		useNoProxy.setAlignmentX(LEFT_ALIGNMENT);
+		gbc.gridx = 0;
+		gbc.gridy = 1;
+		gbc.gridwidth = 2;
+		gbc.weightx = 0.0;
+		gbc.weighty = 0.0;
+		gbc.fill = NONE;
+		gbc.insets = new Insets(10, 0, 0, 0);
+		this.add(useNoProxy, gbc);
+		ActionListener useNoProxyListener = new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent arg0) {
+				shownOption = USE_NO_PROXY_OPTION;
+				populateFields();
+			}
+		};
+		useNoProxy.addActionListener(useNoProxyListener);
+
+		useSystemProperties = new JRadioButton("Use system properties");
+		useSystemProperties.setAlignmentX(LEFT_ALIGNMENT);
+		gbc.gridx = 0;
+		gbc.gridy = 2;
+		gbc.insets = new Insets(0, 0, 0, 0);
+		this.add(useSystemProperties, gbc);
+		ActionListener systemPropertiesListener = new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent arg0) {
+				shownOption = USE_SYSTEM_PROPERTIES_OPTION;
+				populateFields();
+			}
+		};
+		useSystemProperties.addActionListener(systemPropertiesListener);
+
+		useSpecifiedValues = new JRadioButton("Use specified values");
+		useSpecifiedValues.setAlignmentX(LEFT_ALIGNMENT);
+		gbc.gridx = 0;
+		gbc.gridy = 3;
+		this.add(useSpecifiedValues, gbc);
+		ActionListener specifiedValuesListener = new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent arg0) {
+				shownOption = USE_SPECIFIED_VALUES_OPTION;
+				populateFields();
+			}
+		};
+		useSpecifiedValues.addActionListener(specifiedValuesListener);
+
+		ButtonGroup bg = new ButtonGroup();
+		bg.add(useSystemProperties);
+		bg.add(useSpecifiedValues);
+		bg.add(useNoProxy);
+
+		/**
+		 * Create the fields to show the HTTP proxy property values. These
+		 * become editable if the shown option is to use specified values.
+		 */
+		proxyHostField = new JTextField(TEXTFIELD_SIZE);
+		gbc.gridx = 0;
+		gbc.gridy = 4;
+		gbc.gridwidth = 1;
+		gbc.fill = NONE;
+		gbc.insets = new Insets(10, 0, 0, 0);
+		this.add(new JLabel("Proxy host"), gbc);
+		gbc.gridx = 1;
+		gbc.gridy = 4;
+		gbc.gridwidth = 1;
+		gbc.fill = HORIZONTAL;
+		this.add(proxyHostField, gbc);
+
+		proxyPortField = new JTextField(TEXTFIELD_SIZE);
+		gbc.gridx = 0;
+		gbc.gridy = 5;
+		gbc.gridwidth = 1;
+		gbc.fill = NONE;
+		gbc.insets = new Insets(0, 0, 0, 0);
+		this.add(new JLabel("Proxy port"), gbc);
+		gbc.gridx = 1;
+		gbc.gridy = 5;
+		gbc.gridwidth = 1;
+		gbc.fill = HORIZONTAL;
+		this.add(proxyPortField, gbc);
+
+		proxyUserField = new JTextField(TEXTFIELD_SIZE);
+		gbc.gridx = 0;
+		gbc.gridy = 6;
+		gbc.gridwidth = 1;
+		gbc.fill = NONE;
+		this.add(new JLabel("Proxy user"), gbc);
+		gbc.gridx = 1;
+		gbc.gridy = 6;
+		gbc.gridwidth = 1;
+		gbc.fill = HORIZONTAL;
+		this.add(proxyUserField, gbc);
+
+		proxyPasswordField = new JTextField(TEXTFIELD_SIZE);
+		gbc.gridx = 0;
+		gbc.gridy = 7;
+		gbc.gridwidth = 1;
+		gbc.fill = NONE;
+		this.add(new JLabel("Proxy password"), gbc);
+		gbc.gridx = 1;
+		gbc.gridy = 7;
+		gbc.gridwidth = 1;
+		gbc.fill = HORIZONTAL;
+		this.add(proxyPasswordField, gbc);
+
+		nonProxyHostsArea = new DialogTextArea(10, 40);
+		nonProxyScrollPane = new JScrollPane(nonProxyHostsArea);
+		nonProxyScrollPane
+				.setHorizontalScrollBarPolicy(HORIZONTAL_SCROLLBAR_AS_NEEDED);
+		nonProxyScrollPane
+				.setVerticalScrollBarPolicy(VERTICAL_SCROLLBAR_AS_NEEDED);
+		// nonProxyScrollPane.setPreferredSize(new Dimension(300, 500));
+		gbc.gridx = 0;
+		gbc.gridy = 8;
+		gbc.gridwidth = 2;
+		gbc.fill = NONE;
+		gbc.insets = new Insets(10, 0, 0, 0);
+		this.add(new JLabel("Non-proxy hosts"), gbc);
+		gbc.gridx = 0;
+		gbc.gridy = 9;
+		gbc.weightx = 1.0;
+		gbc.weighty = 1.0;
+		gbc.gridwidth = 2;
+		gbc.insets = new Insets(0, 0, 0, 0);
+		gbc.fill = BOTH;
+		this.add(nonProxyScrollPane, gbc);
+
+		// Add buttons panel
+		gbc.gridx = 0;
+		gbc.gridy = 10;
+		gbc.weightx = 0.0;
+		gbc.weighty = 0.0;
+		gbc.gridwidth = 2;
+		gbc.fill = HORIZONTAL;
+		gbc.anchor = CENTER;
+		gbc.insets = new Insets(10, 0, 0, 0);
+		this.add(createButtonPanel(), gbc);
+
+		setFields();
+	}
+
+	/**
+	 * Populate the fields in the property panel according to which option is
+	 * being shown and the stored values within the
+	 * {@link HttpProxyConfiguration}.
+	 */
+	private void populateFields() {
+		/**
+		 * Editing of the property fields is only available when the option is
+		 * to use the specified values.
+		 */
+		boolean editingEnabled = shownOption
+				.equals(USE_SPECIFIED_VALUES_OPTION);
+
+		if (shownOption.equals(USE_SYSTEM_PROPERTIES_OPTION)) {
+			proxyHostField.setText(httpProxyConfiguration
+					.getProperty(SYSTEM_PROXY_HOST));
+			proxyPortField.setText(httpProxyConfiguration
+					.getProperty(SYSTEM_PROXY_PORT));
+			proxyUserField.setText(httpProxyConfiguration
+					.getProperty(SYSTEM_PROXY_USER));
+			proxyPasswordField.setText(httpProxyConfiguration
+					.getProperty(SYSTEM_PROXY_PASSWORD));
+			nonProxyHostsArea.setText(httpProxyConfiguration
+					.getProperty(SYSTEM_NON_PROXY_HOSTS));
+		} else if (shownOption.equals(USE_SPECIFIED_VALUES_OPTION)) {
+			proxyHostField.setText(httpProxyConfiguration
+					.getProperty(TAVERNA_PROXY_HOST));
+			proxyPortField.setText(httpProxyConfiguration
+					.getProperty(TAVERNA_PROXY_PORT));
+			proxyUserField.setText(httpProxyConfiguration
+					.getProperty(TAVERNA_PROXY_USER));
+			proxyPasswordField.setText(httpProxyConfiguration
+					.getProperty(TAVERNA_PROXY_PASSWORD));
+			nonProxyHostsArea.setText(httpProxyConfiguration
+					.getProperty(TAVERNA_NON_PROXY_HOSTS));
+		} else {
+			proxyHostField.setText(null);
+			proxyPortField.setText(null);
+			proxyUserField.setText(null);
+			proxyPasswordField.setText(null);
+			nonProxyHostsArea.setText(null);
+		}
+
+		proxyHostField.setEnabled(editingEnabled);
+		proxyPortField.setEnabled(editingEnabled);
+		proxyUserField.setEnabled(editingEnabled);
+		proxyPasswordField.setEnabled(editingEnabled);
+		nonProxyHostsArea.setEnabled(editingEnabled);
+		nonProxyHostsArea.setEditable(editingEnabled);
+		nonProxyScrollPane.setEnabled(editingEnabled);
+	}
+
+	/**
+	 * Create the panel to contain the buttons
+	 * 
+	 * @return
+	 */
+	@SuppressWarnings("serial")
+	private JPanel createButtonPanel() {
+		final JPanel panel = new JPanel();
+
+		/**
+		 * The helpButton shows help about the current component
+		 */
+		JButton helpButton = new JButton(new AbstractAction("Help") {
+			@Override
+			public void actionPerformed(ActionEvent arg0) {
+				showHelp(panel);
+			}
+		});
+		panel.add(helpButton);
+
+		/**
+		 * The resetButton changes the property values shown to those
+		 * corresponding to the configuration currently applied.
+		 */
+		JButton resetButton = new JButton(new AbstractAction("Reset") {
+			@Override
+			public void actionPerformed(ActionEvent arg0) {
+				setFields();
+			}
+		});
+		panel.add(resetButton);
+
+		/**
+		 * The applyButton applies the shown field values to the
+		 * {@link HttpProxyConfiguration} and saves them for future.
+		 */
+		JButton applyButton = new JButton(new AbstractAction("Apply") {
+			@Override
+			public void actionPerformed(ActionEvent arg0) {
+				applySettings();
+				setFields();
+			}
+		});
+		panel.add(applyButton);
+
+		return panel;
+	}
+
+	/**
+	 * Checks that the specified values for the HTTP properties are a valid
+	 * combination and, if so, saves them for future use. It does not apply them
+	 * to the currently executing Taverna.
+	 */
+	private void saveSettings() {
+		if (useSystemProperties.isSelected()) {
+			httpProxyConfiguration.setProperty(PROXY_USE_OPTION,
+					USE_SYSTEM_PROPERTIES_OPTION);
+		} else if (useNoProxy.isSelected()) {
+			httpProxyConfiguration.setProperty(PROXY_USE_OPTION,
+					USE_NO_PROXY_OPTION);
+		} else {
+			if (validateFields()) {
+				httpProxyConfiguration.setProperty(PROXY_USE_OPTION,
+						USE_SPECIFIED_VALUES_OPTION);
+				httpProxyConfiguration.setProperty(TAVERNA_PROXY_HOST,
+						proxyHostField.getText());
+				httpProxyConfiguration.setProperty(TAVERNA_PROXY_PORT,
+						proxyPortField.getText());
+				httpProxyConfiguration.setProperty(TAVERNA_PROXY_USER,
+						proxyUserField.getText());
+				httpProxyConfiguration.setProperty(TAVERNA_PROXY_PASSWORD,
+						proxyPasswordField.getText());
+				httpProxyConfiguration.setProperty(TAVERNA_NON_PROXY_HOSTS,
+						nonProxyHostsArea.getText());
+			}
+		}
+	}
+
+	/**
+	 * Validates and, where appropriate formats, the properties values specified
+	 * for HTTP Proxy configuration.
+	 * 
+	 * @return
+	 */
+	private boolean validateFields() {
+		boolean result = true;
+		result = result && validateHostField();
+		result = result && validatePortField();
+		result = result && validateUserField();
+		result = result && validatePasswordField();
+		result = result && validateNonProxyHostsArea();
+		return result;
+	}
+
+	/**
+	 * Checks that, if a value is specified for non-proxy hosts then a proxy
+	 * host has also been specified. Formats the non-proxy hosts string so that
+	 * if the user has entered the hosts on separate lines, then the stored
+	 * values are separated by bars.
+	 * 
+	 * @return
+	 */
+	private boolean validateNonProxyHostsArea() {
+		boolean result = true;
+		String value = nonProxyHostsArea.getText();
+		if ((value != null) && (!value.equals(""))) {
+			value = value.replaceAll("\\n", "|");
+			nonProxyHostsArea.setText(value);
+			result = result
+					&& dependsUpon("non-proxy host", "host",
+							proxyHostField.getText());
+		}
+		return result;
+	}
+
+	/**
+	 * Checks that, if a password has been specified, then a user has also been
+	 * specified.
+	 * 
+	 * @return
+	 */
+	private boolean validatePasswordField() {
+		boolean result = true;
+		String value = proxyPasswordField.getText();
+		if ((value != null) && !value.isEmpty())
+			result = result
+					&& dependsUpon("password", "user", proxyHostField.getText());
+		return result;
+	}
+
+	/**
+	 * Checks that if a user has been specified, then a host has also been
+	 * specified.
+	 * 
+	 * @return
+	 */
+	private boolean validateUserField() {
+		boolean result = true;
+		String value = proxyUserField.getText();
+		if ((value != null) && !value.isEmpty())
+			result = result
+					&& dependsUpon("user", "host", proxyHostField.getText());
+		return result;
+	}
+
+	/**
+	 * Checks that if a port has been specified then a host has also been
+	 * specified. Checks that the port number is a non-negative integer. If the
+	 * port has not been specified, then if a host has been specified, the
+	 * default value 80 is used.
+	 * 
+	 * @return
+	 */
+	private boolean validatePortField() {
+		boolean result = true;
+		String value = proxyPortField.getText();
+		if ((value != null) && (!value.equals(""))) {
+			result = result
+					&& dependsUpon("port", "host", proxyHostField.getText());
+			try {
+				int parsedNumber = Integer.parseInt(value);
+				if (parsedNumber <= 0) {
+					showMessageDialog(this, "The port must be non-negative");
+					result = false;
+				}
+			} catch (NumberFormatException e) {
+				showMessageDialog(this, "The port must be an integer");
+				result = false;
+			}
+		} else {
+			String hostField = proxyHostField.getText();
+			if ((hostField != null) && !hostField.isEmpty())
+				proxyPortField.setText("80");
+		}
+		return result;
+	}
+
+	/**
+	 * Checks if the targetValue has been specified. If not then a message is
+	 * displayed indicating that the dependent cannot be specified with the
+	 * target.
+	 * 
+	 * @param dependent
+	 * @param target
+	 * @param targetValue
+	 * @return
+	 */
+	private boolean dependsUpon(String dependent, String target,
+			String targetValue) {
+		boolean result = true;
+		if ((targetValue == null) || target.equals("")) {
+			showMessageDialog(this, "A " + dependent
+					+ " cannot be specified without a " + target);
+			result = false;
+		}
+		return result;
+	}
+
+	/**
+	 * Could validate the host field e.g. by establishing a connection.
+	 * Currently no validation is done.
+	 * 
+	 * @return
+	 */
+	private boolean validateHostField() {
+		boolean result = true;
+		// String value = proxyHostField.getText();
+		return result;
+	}
+
+	/**
+	 * Save the currently set field values (if valid) to the
+	 * {@link HttpProxyConfiguration}. Also applies those values to the
+	 * currently running Taverna.
+	 */
+	private void applySettings() {
+		if (validateFields()) {
+			saveSettings();
+			httpProxyConfiguration.changeProxySettings();
+		}
+	}
+
+	/**
+	 * Set the shown field values to those currently in use (i.e. last saved
+	 * configuration).
+	 */
+	private void setFields() {
+		shownOption = httpProxyConfiguration.getProperty(PROXY_USE_OPTION);
+		useSystemProperties.setSelected(shownOption
+				.equals(USE_SYSTEM_PROPERTIES_OPTION));
+		useSpecifiedValues.setSelected(shownOption
+				.equals(USE_SPECIFIED_VALUES_OPTION));
+		useNoProxy.setSelected(shownOption.equals(USE_NO_PROXY_OPTION));
+		populateFields();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/8c4b365e/taverna-workbench-httpproxy-config/src/main/java/net/sf/taverna/t2/workbench/httpproxy/config/HttpProxyConfigurationUIFactory.java
----------------------------------------------------------------------
diff --git a/taverna-workbench-httpproxy-config/src/main/java/net/sf/taverna/t2/workbench/httpproxy/config/HttpProxyConfigurationUIFactory.java b/taverna-workbench-httpproxy-config/src/main/java/net/sf/taverna/t2/workbench/httpproxy/config/HttpProxyConfigurationUIFactory.java
new file mode 100644
index 0000000..9f6ac8c
--- /dev/null
+++ b/taverna-workbench-httpproxy-config/src/main/java/net/sf/taverna/t2/workbench/httpproxy/config/HttpProxyConfigurationUIFactory.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * 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.httpproxy.config;
+
+import javax.swing.JPanel;
+
+import uk.org.taverna.configuration.Configurable;
+import uk.org.taverna.configuration.ConfigurationUIFactory;
+import uk.org.taverna.configuration.proxy.HttpProxyConfiguration;
+
+/**
+ * A Factory to create a HttpProxyConfiguration
+ *
+ * @author alanrw
+ * @author David Withers
+ */
+public class HttpProxyConfigurationUIFactory implements ConfigurationUIFactory {
+	private HttpProxyConfiguration httpProxyConfiguration;
+
+	@Override
+	public boolean canHandle(String uuid) {
+		return uuid.equals(getConfigurable().getUUID());
+	}
+
+	@Override
+	public JPanel getConfigurationPanel() {
+		return new HttpProxyConfigurationPanel(httpProxyConfiguration);
+	}
+
+	@Override
+	public Configurable getConfigurable() {
+		return httpProxyConfiguration;
+	}
+
+	public void setHttpProxyConfiguration(HttpProxyConfiguration httpProxyConfiguration) {
+		this.httpProxyConfiguration = httpProxyConfiguration;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/8c4b365e/taverna-workbench-httpproxy-config/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.configuration.ConfigurationUIFactory
----------------------------------------------------------------------
diff --git a/taverna-workbench-httpproxy-config/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.configuration.ConfigurationUIFactory b/taverna-workbench-httpproxy-config/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.configuration.ConfigurationUIFactory
new file mode 100644
index 0000000..d87772b
--- /dev/null
+++ b/taverna-workbench-httpproxy-config/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.configuration.ConfigurationUIFactory
@@ -0,0 +1 @@
+net.sf.taverna.t2.workbench.httpproxy.config.HttpProxyConfigurationUIFactory
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/8c4b365e/taverna-workbench-httpproxy-config/src/main/resources/META-INF/spring/httpproxy-config-context-osgi.xml
----------------------------------------------------------------------
diff --git a/taverna-workbench-httpproxy-config/src/main/resources/META-INF/spring/httpproxy-config-context-osgi.xml b/taverna-workbench-httpproxy-config/src/main/resources/META-INF/spring/httpproxy-config-context-osgi.xml
new file mode 100644
index 0000000..631bdb4
--- /dev/null
+++ b/taverna-workbench-httpproxy-config/src/main/resources/META-INF/spring/httpproxy-config-context-osgi.xml
@@ -0,0 +1,13 @@
+<?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="HttpProxyConfigurationUIFactory" interface="uk.org.taverna.configuration.ConfigurationUIFactory" />
+
+	<reference id="httpProxyConfiguration" interface="uk.org.taverna.configuration.proxy.HttpProxyConfiguration" />
+
+</beans:beans>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/8c4b365e/taverna-workbench-httpproxy-config/src/main/resources/META-INF/spring/httpproxy-config-context.xml
----------------------------------------------------------------------
diff --git a/taverna-workbench-httpproxy-config/src/main/resources/META-INF/spring/httpproxy-config-context.xml b/taverna-workbench-httpproxy-config/src/main/resources/META-INF/spring/httpproxy-config-context.xml
new file mode 100644
index 0000000..6d6060f
--- /dev/null
+++ b/taverna-workbench-httpproxy-config/src/main/resources/META-INF/spring/httpproxy-config-context.xml
@@ -0,0 +1,10 @@
+<?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="HttpProxyConfigurationUIFactory" class="net.sf.taverna.t2.workbench.httpproxy.config.HttpProxyConfigurationUIFactory">
+		<property name="httpProxyConfiguration" ref="httpProxyConfiguration" />
+	</bean>
+
+</beans>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/8c4b365e/taverna-workbench-iteration-strategy-ui/pom.xml
----------------------------------------------------------------------
diff --git a/taverna-workbench-iteration-strategy-ui/pom.xml b/taverna-workbench-iteration-strategy-ui/pom.xml
new file mode 100644
index 0000000..0b6ff81
--- /dev/null
+++ b/taverna-workbench-iteration-strategy-ui/pom.xml
@@ -0,0 +1,63 @@
+<?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-components</artifactId>
+		<version>2.0-SNAPSHOT</version>
+	</parent>
+	<groupId>net.sf.taverna.t2.ui-components</groupId>
+	<artifactId>iteration-strategy-ui</artifactId>
+	<packaging>bundle</packaging>
+	<name>Menu generation API</name>
+	<description>An SPI system for building UI menues</description>
+	<dependencies>
+		<dependency>
+			<groupId>net.sf.taverna.t2.core</groupId>
+			<artifactId>workflowmodel-api</artifactId>
+			<version>${t2.core.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.taverna.t2.lang</groupId>
+			<artifactId>ui</artifactId>
+			<version>${t2.lang.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.taverna.t2.ui-api</groupId>
+			<artifactId>workbench-api</artifactId>
+			<version>${t2.ui.api.version}</version>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.taverna.t2.ui-api</groupId>
+			<artifactId>contextual-views-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>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>junit</groupId>
+			<artifactId>junit</artifactId>
+			<scope>test</scope>
+		</dependency>
+		<dependency>
+			<groupId>net.sf.taverna.t2.core</groupId>
+			<artifactId>workflowmodel-impl</artifactId>
+			<version>${t2.core.version}</version>
+			<!-- <scope>test</scope> -->
+		</dependency>
+	</dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/8c4b365e/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/IterationStrategyIcons.java
----------------------------------------------------------------------
diff --git a/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/IterationStrategyIcons.java b/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/IterationStrategyIcons.java
new file mode 100644
index 0000000..350c0cc
--- /dev/null
+++ b/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/IterationStrategyIcons.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * 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.iterationstrategy;
+
+import javax.swing.ImageIcon;
+
+import org.apache.log4j.Logger;
+
+public class IterationStrategyIcons {
+
+	private static Logger logger = Logger
+			.getLogger(IterationStrategyIcons.class);
+
+	public static ImageIcon joinIteratorIcon, lockStepIteratorIcon,
+			leafnodeicon;
+
+	static {
+		try {
+			Class<?> c = IterationStrategyIcons.class;
+			joinIteratorIcon = new ImageIcon(c
+					.getResource("icons/crossproducticon.png"));
+			lockStepIteratorIcon = new ImageIcon(c
+					.getResource("icons/dotproducticon.png"));
+			leafnodeicon = new ImageIcon(c
+					.getResource("icons/leafnodeicon.png"));
+		} catch (Exception ex) {
+			logger.warn("Could not find icon", ex);
+		}
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/8c4b365e/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/contextview/IterationStrategyConfigurationDialog.java
----------------------------------------------------------------------
diff --git a/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/contextview/IterationStrategyConfigurationDialog.java b/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/contextview/IterationStrategyConfigurationDialog.java
new file mode 100644
index 0000000..1af83cb
--- /dev/null
+++ b/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/contextview/IterationStrategyConfigurationDialog.java
@@ -0,0 +1,148 @@
+/**
+ *
+ */
+package net.sf.taverna.t2.workbench.iterationstrategy.contextview;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Frame;
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+
+import net.sf.taverna.t2.workbench.edits.EditManager;
+import net.sf.taverna.t2.workbench.file.FileManager;
+import net.sf.taverna.t2.workbench.helper.HelpEnabledDialog;
+import net.sf.taverna.t2.workbench.iterationstrategy.editor.IterationStrategyEditorControl;
+import net.sf.taverna.t2.workflowmodel.Edit;
+import net.sf.taverna.t2.workflowmodel.EditException;
+import net.sf.taverna.t2.workflowmodel.Edits;
+import net.sf.taverna.t2.workflowmodel.Processor;
+import net.sf.taverna.t2.workflowmodel.processor.iteration.IterationStrategy;
+import net.sf.taverna.t2.workflowmodel.processor.iteration.IterationStrategyStack;
+
+import org.apache.log4j.Logger;
+
+/**
+ * @author alanrw
+ *
+ */
+@SuppressWarnings("serial")
+public class IterationStrategyConfigurationDialog extends HelpEnabledDialog {
+
+	private static Logger logger = Logger
+	.getLogger(IterationStrategyConfigurationDialog.class);
+
+	private final EditManager editManager;
+	private final FileManager fileManager;
+
+
+	private final Frame owner;
+	private final Processor processor;
+	private final IterationStrategyStack originalStack;
+
+	private IterationStrategyStack workingStack;
+
+	public IterationStrategyConfigurationDialog(Frame owner, Processor processor, IterationStrategyStack iStack, EditManager editManager, FileManager fileManager) {
+		super (owner, "List handling for " + processor.getLocalName(), true, null);
+		this.owner = owner;
+		this.processor = processor;
+		this.originalStack = iStack;
+		this.editManager = editManager;
+		this.fileManager = fileManager;
+		this.workingStack = IterationStrategyContextualView.copyIterationStrategyStack(originalStack);
+		IterationStrategy iterationStrategy = IterationStrategyContextualView.getIterationStrategy(workingStack);
+		IterationStrategyEditorControl iterationStrategyEditorControl = new IterationStrategyEditorControl(
+				iterationStrategy);
+		this.add(iterationStrategyEditorControl, BorderLayout.CENTER);
+
+		JPanel buttonPanel = new JPanel();
+		buttonPanel.setLayout(new FlowLayout());
+
+		JButton okButton = new JButton(new OKAction(this));
+		buttonPanel.add(okButton);
+
+		JButton resetButton = new JButton(new ResetAction(
+				iterationStrategyEditorControl));
+		buttonPanel.add(resetButton);
+
+		JButton cancelButton = new JButton(new CancelAction(this));
+		buttonPanel.add(cancelButton);
+
+		this.add(buttonPanel, BorderLayout.SOUTH);
+		this.pack();
+		this.setSize(new Dimension(getPreferredSize().width, getPreferredSize().height > 400 ? 400 : getPreferredSize().height));
+	}
+
+	private final class OKAction extends AbstractAction {
+		private final JDialog dialog;
+
+		private OKAction(JDialog dialog) {
+			super("OK");
+			this.dialog = dialog;
+		}
+
+		public void actionPerformed(ActionEvent e) {
+			Edits edits = editManager.getEdits();
+			try {
+				Edit<?> edit = edits.getSetIterationStrategyStackEdit(
+						processor,
+						IterationStrategyContextualView.copyIterationStrategyStack(workingStack));
+				editManager.doDataflowEdit(
+						fileManager.getCurrentDataflow(), edit);
+				dialog.setVisible(false);
+			} catch (RuntimeException ex) {
+				logger.warn("Could not set list handling", ex);
+				JOptionPane.showMessageDialog(owner,
+						"Can't set list handling",
+						"An error occured when setting list handling: "
+								+ ex.getMessage(),
+						JOptionPane.ERROR_MESSAGE);
+			} catch (EditException ex) {
+				logger.warn("Could not set list handling", ex);
+				JOptionPane.showMessageDialog(owner,
+						"Can't set list handling",
+						"An error occured when setting list handling: "
+								+ ex.getMessage(),
+						JOptionPane.ERROR_MESSAGE);
+			}
+		}
+	}
+
+	private final class ResetAction extends AbstractAction {
+		private final IterationStrategyEditorControl strategyEditorControl;
+
+		private ResetAction(
+				IterationStrategyEditorControl strategyEditorControl) {
+			super("Reset");
+			this.strategyEditorControl = strategyEditorControl;
+		}
+
+		public void actionPerformed(ActionEvent e) {
+			workingStack = IterationStrategyContextualView.copyIterationStrategyStack(originalStack);
+			strategyEditorControl
+					.setIterationStrategy(IterationStrategyContextualView.getIterationStrategy(workingStack));
+		}
+
+	}
+
+	private final class CancelAction extends AbstractAction {
+		private final JDialog dialog;
+
+		private CancelAction(JDialog dialog) {
+			super("Cancel");
+			this.dialog = dialog;
+		}
+
+		public void actionPerformed(ActionEvent e) {
+			dialog.setVisible(false);
+		}
+
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/8c4b365e/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/contextview/IterationStrategyContextualView.java
----------------------------------------------------------------------
diff --git a/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/contextview/IterationStrategyContextualView.java b/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/contextview/IterationStrategyContextualView.java
new file mode 100644
index 0000000..369bea4
--- /dev/null
+++ b/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/contextview/IterationStrategyContextualView.java
@@ -0,0 +1,231 @@
+/*******************************************************************************
+ * 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.iterationstrategy.contextview;
+
+import java.awt.Frame;
+import java.awt.event.ActionEvent;
+import java.util.List;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.JComponent;
+
+import net.sf.taverna.t2.workbench.edits.EditManager;
+import net.sf.taverna.t2.workbench.file.FileManager;
+import net.sf.taverna.t2.workbench.helper.HelpEnabledDialog;
+import net.sf.taverna.t2.workbench.iterationstrategy.editor.IterationStrategyTree;
+import net.sf.taverna.t2.workbench.ui.views.contextualviews.ContextualView;
+import net.sf.taverna.t2.workflowmodel.Processor;
+import net.sf.taverna.t2.workflowmodel.processor.iteration.IterationStrategy;
+import net.sf.taverna.t2.workflowmodel.processor.iteration.IterationStrategyStack;
+import net.sf.taverna.t2.workflowmodel.processor.iteration.impl.IterationStrategyImpl;
+import net.sf.taverna.t2.workflowmodel.processor.iteration.impl.IterationStrategyStackImpl;
+
+import org.apache.log4j.Logger;
+import org.jdom.Content;
+import org.jdom.Element;
+import org.jdom.filter.ElementFilter;
+
+/**
+ * Contextual view of an {@link IterationStrategyStack}.
+ *
+ * @author Stian Soiland-Reyes
+ *
+ */
+public class IterationStrategyContextualView extends ContextualView {
+
+	private static Logger logger = Logger
+			.getLogger(IterationStrategyContextualView.class);
+
+	private EditManager editManager;
+
+	private FileManager fileManager;
+
+	private IterationStrategyStack iterationStack;
+
+	private final Processor processor;
+
+	private IterationStrategyTree strategyTree = new IterationStrategyTree();
+
+	static {
+
+// This should be enabled and modified for T2-822
+/*		editManager.addObserver(new Observer<EditManagerEvent> () {
+
+			private void examineEdit(Edit edit) {
+				if (edit instanceof ConnectDatalinkEdit) {
+					processConnectDatalinkEdit((ConnectDatalinkEdit) edit);
+				}
+				if (edit instanceof CompoundEdit) {
+					processCompoundEdit((CompoundEdit) edit);
+				}
+			}
+
+			private void processConnectDatalinkEdit(ConnectDatalinkEdit edit) {
+				Datalink d = ((ConnectDatalinkEdit) edit).getSubject();
+				EventHandlingInputPort sink = d.getSink();
+				if (sink instanceof ProcessorInputPort) {
+					ProcessorInputPort pip = (ProcessorInputPort) sink;
+					Processor p = pip.getProcessor();
+					final HelpEnabledDialog dialog = new IterationStrategyConfigurationDialog(null, p, copyIterationStrategyStack(p.getIterationStrategy()));
+					dialog.setVisible(true);
+				}
+			}
+
+			private void processCompoundEdit(CompoundEdit edit) {
+				for (Edit e : edit.getChildEdits()) {
+					examineEdit(e);
+				}
+			}
+
+			@Override
+			public void notify(Observable<EditManagerEvent> sender,
+					EditManagerEvent message) throws Exception {
+				if (!(message instanceof DataflowEditEvent)) {
+					return;
+				}
+				examineEdit(message.getEdit());
+			}});*/
+	}
+
+	public IterationStrategyContextualView(Processor processor, EditManager editManager, FileManager fileManager) {
+		if (processor == null || processor.getIterationStrategy() == null) {
+			throw new NullPointerException(
+					"Iteration strategy stack can't be null");
+		}
+		this.processor = processor;
+		this.editManager = editManager;
+		this.fileManager = fileManager;
+		refreshIterationStrategyStack();
+		initView();
+	}
+
+	@Override
+	public Action getConfigureAction(final Frame owner) {
+		return new ConfigureIterationStrategyAction(owner);
+	}
+
+	public Processor getProcessor() {
+		return processor;
+	}
+
+	@Override
+	public void refreshView() {
+		refreshIterationStrategyStack();
+		strategyTree.setIterationStrategy(getIterationStrategy(iterationStack));
+	}
+
+	public static IterationStrategyStack copyIterationStrategyStack(
+			IterationStrategyStack stack) {
+		Element asXML = ((IterationStrategyStackImpl)stack).asXML();
+		stripEmptyElements(asXML);
+		IterationStrategyStackImpl copyStack = new IterationStrategyStackImpl();
+		copyStack.configureFromElement(asXML);
+		if (copyStack.getStrategies().isEmpty()) {
+			copyStack.addStrategy(new IterationStrategyImpl());
+		}
+		return copyStack;
+	}
+
+	private static void stripEmptyElements(Element asXML) {
+		int childCount = asXML.getContent().size();
+		int index = 0;
+		while (index < childCount) {
+			Content child = asXML.getContent(index);
+			if (child instanceof Element) {
+				Element childElement = (Element) child;
+				if (childElement.getName().equals("port")) {
+					index++;
+				}
+				else if (childElement.getDescendants(new ElementFilter("port")).hasNext()) {
+					stripEmptyElements(childElement);
+					index++;
+				} else {
+					asXML.removeContent(childElement);
+					childCount--;
+				}
+			}
+		}
+	}
+
+	public static IterationStrategy getIterationStrategy(IterationStrategyStack iStack) {
+		List<? extends IterationStrategy> strategies = iStack
+				.getStrategies();
+		if (strategies.isEmpty()) {
+			throw new IllegalStateException("Empty iteration stack");
+		}
+		IterationStrategy strategy = strategies.get(0);
+		if (!(strategy instanceof IterationStrategyImpl)) {
+			throw new IllegalStateException(
+					"Can't edit unknown iteration strategy implementation "
+							+ strategy);
+		}
+		return (IterationStrategyImpl) strategy;
+	}
+
+	private void refreshIterationStrategyStack() {
+		IterationStrategyStack originalIterationStrategy = processor
+				.getIterationStrategy();
+		if (!(originalIterationStrategy instanceof IterationStrategyStackImpl)) {
+			throw new IllegalStateException(
+					"Unknown iteration strategy implementation "
+							+ originalIterationStrategy);
+		}
+		this.iterationStack = copyIterationStrategyStack((IterationStrategyStackImpl) originalIterationStrategy);
+	}
+
+	@Override
+	public JComponent getMainFrame() {
+		refreshView();
+		return strategyTree;
+	}
+
+	@Override
+	public String getViewTitle() {
+		return "List handling";
+	}
+
+	private final class ConfigureIterationStrategyAction extends AbstractAction {
+		private final Frame owner;
+
+		private ConfigureIterationStrategyAction(Frame owner) {
+			super("Configure");
+			this.owner = owner;
+		}
+
+		public void actionPerformed(ActionEvent e) {
+			final HelpEnabledDialog dialog = new IterationStrategyConfigurationDialog(owner, processor, iterationStack, editManager, fileManager);
+			dialog.setVisible(true);
+			refreshView();
+		}
+
+
+
+	}
+
+	@Override
+	public int getPreferredPosition() {
+		return 200;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/8c4b365e/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/contextview/IterationStrategyContextualViewFactory.java
----------------------------------------------------------------------
diff --git a/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/contextview/IterationStrategyContextualViewFactory.java b/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/contextview/IterationStrategyContextualViewFactory.java
new file mode 100644
index 0000000..a970239
--- /dev/null
+++ b/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/contextview/IterationStrategyContextualViewFactory.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * 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.iterationstrategy.contextview;
+
+import java.util.Arrays;
+import java.util.List;
+
+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 net.sf.taverna.t2.workflowmodel.Processor;
+
+public class IterationStrategyContextualViewFactory implements
+		ContextualViewFactory<Processor> {
+
+	private EditManager editManager;
+	private FileManager fileManager;
+
+	public boolean canHandle(Object selection) {
+		return selection instanceof Processor;
+	}
+
+	public List<ContextualView> getViews(Processor p) {
+		return Arrays.asList(new ContextualView[] {new IterationStrategyContextualView(p, editManager, fileManager)});
+	}
+
+	public void setEditManager(EditManager editManager) {
+		this.editManager = editManager;
+	}
+
+	public void setFileManager(FileManager fileManager) {
+		this.fileManager = fileManager;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/8c4b365e/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/editor/IterationStrategyCellRenderer.java
----------------------------------------------------------------------
diff --git a/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/editor/IterationStrategyCellRenderer.java b/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/editor/IterationStrategyCellRenderer.java
new file mode 100644
index 0000000..4c31574
--- /dev/null
+++ b/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/editor/IterationStrategyCellRenderer.java
@@ -0,0 +1,74 @@
+/*******************************************************************************
+ * 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.iterationstrategy.editor;
+
+import java.awt.Component;
+
+import javax.swing.JTree;
+import javax.swing.tree.DefaultTreeCellRenderer;
+
+import net.sf.taverna.t2.workbench.icons.WorkbenchIcons;
+import net.sf.taverna.t2.workbench.iterationstrategy.IterationStrategyIcons;
+import net.sf.taverna.t2.workflowmodel.processor.iteration.CrossProduct;
+import net.sf.taverna.t2.workflowmodel.processor.iteration.DotProduct;
+import net.sf.taverna.t2.workflowmodel.processor.iteration.NamedInputPortNode;
+
+import org.apache.log4j.Logger;
+
+@SuppressWarnings("serial")
+final class IterationStrategyCellRenderer extends DefaultTreeCellRenderer {
+
+	@SuppressWarnings("unused")
+	private static Logger logger = Logger
+			.getLogger(IterationStrategyCellRenderer.class);
+
+	@Override
+	public Component getTreeCellRendererComponent(JTree tree, Object value,
+			boolean selected, boolean expanded, boolean leaf, int row,
+			boolean hasFocus) {
+		super.getTreeCellRendererComponent(tree, value, selected, expanded,
+				leaf, row, hasFocus);
+		if (value instanceof CrossProduct) {
+			setIcon(IterationStrategyIcons.joinIteratorIcon);
+			setText("Cross product");
+		} else if (value instanceof DotProduct) {
+			setIcon(IterationStrategyIcons.lockStepIteratorIcon);
+			setText("Dot product");
+		} else if (value instanceof NamedInputPortNode) {
+			setIcon(IterationStrategyIcons.leafnodeicon);
+			NamedInputPortNode namedInput = (NamedInputPortNode) value;
+			setText(namedInput.getPortName());
+		} else {
+			setText("List handling");
+			if (!leaf){
+				if (expanded) {
+					setIcon(WorkbenchIcons.folderOpenIcon);
+				} else {
+					setIcon(WorkbenchIcons.folderClosedIcon);
+				}
+			}
+		}
+		return this;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/8c4b365e/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/editor/IterationStrategyEditor.java
----------------------------------------------------------------------
diff --git a/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/editor/IterationStrategyEditor.java b/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/editor/IterationStrategyEditor.java
new file mode 100644
index 0000000..add5201
--- /dev/null
+++ b/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/editor/IterationStrategyEditor.java
@@ -0,0 +1,247 @@
+/*******************************************************************************
+ * 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.iterationstrategy.editor;
+
+import java.awt.GraphicsEnvironment;
+import java.awt.datatransfer.DataFlavor;
+import java.awt.datatransfer.Transferable;
+import java.awt.datatransfer.UnsupportedFlavorException;
+//import java.awt.image.BufferedImage;
+import java.io.IOException;
+
+import javax.swing.DropMode;
+import javax.swing.JComponent;
+import javax.swing.JTree;
+import javax.swing.TransferHandler;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreePath;
+import javax.swing.tree.TreeSelectionModel;
+
+import net.sf.taverna.t2.workbench.ui.zaria.UIComponentSPI;
+import net.sf.taverna.t2.workflowmodel.processor.iteration.AbstractIterationStrategyNode;
+import net.sf.taverna.t2.workflowmodel.processor.iteration.IterationStrategy;
+import net.sf.taverna.t2.workflowmodel.processor.iteration.NamedInputPortNode;
+import net.sf.taverna.t2.workflowmodel.processor.iteration.TerminalNode;
+
+import org.apache.log4j.Logger;
+
+@SuppressWarnings("serial")
+public class IterationStrategyEditor extends IterationStrategyTree implements
+		UIComponentSPI {
+
+	private static Logger logger = Logger
+			.getLogger(IterationStrategyEditor.class);
+
+	//private BufferedImage imgGhost; // The 'drag image'
+
+	// mouse was clicked
+
+	public IterationStrategyEditor() {
+		super();
+		// Make this a drag source
+		if (!GraphicsEnvironment.isHeadless()) {
+			this.setDragEnabled(true);  
+	        this.setDropMode(DropMode.ON_OR_INSERT);  
+	        this.setTransferHandler(new TreeTransferHandler());  
+	        this.getSelectionModel().setSelectionMode(  
+	                TreeSelectionModel.CONTIGUOUS_TREE_SELECTION);  
+	        expandTree();
+		}
+
+		//
+	}
+
+	public IterationStrategyEditor(IterationStrategy theStrategy) {
+		this();
+		setIterationStrategy(theStrategy);
+	}
+
+    /**
+     * 
+     * This code is freely adapted from code derived 
+     *
+     */
+    class TreeTransferHandler extends TransferHandler {  
+        DataFlavor nodesFlavor;
+        DataFlavor[] flavors = new DataFlavor[1];  
+       
+        public TreeTransferHandler() {
+        	getNodesFlavor();
+          }
+        
+        private DataFlavor getNodesFlavor() {
+        	if (nodesFlavor == null) {
+                try {  
+                     nodesFlavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType +
+                             ";class=" + AbstractIterationStrategyNode.class.getName(),
+                             "AbstractIterationStrategyNode",
+                             this.getClass().getClassLoader());  
+                    flavors[0] = nodesFlavor;  
+                } catch(Exception e) {  
+                    logger.error("Problem creating nodesFlavor:" + e);
+                }         		
+        	}
+        	return nodesFlavor;
+        }
+       
+        public boolean canImport(TransferHandler.TransferSupport support) {  
+            if(!support.isDrop()) {
+            	logger.error("isDrop not supported");
+                return false;  
+            }  
+
+            if(!support.isDataFlavorSupported(getNodesFlavor())) {
+            	logger.info("Not correct flavor");
+                return false;  
+            }  
+            // Do not allow a drop on the drag source selections.  
+            JTree.DropLocation dl =  
+                    (JTree.DropLocation)support.getDropLocation();  
+            TreePath dest = dl.getPath();  
+            AbstractIterationStrategyNode destination =  
+                (AbstractIterationStrategyNode)dest.getLastPathComponent();
+            Transferable t = support.getTransferable();
+            if (destination instanceof TerminalNode) {
+            	return false;
+            }
+            try {
+				AbstractIterationStrategyNode node = (AbstractIterationStrategyNode) t.getTransferData(getNodesFlavor());
+				if (node.isNodeDescendant(destination)) {
+					return false;
+				}
+			} catch (UnsupportedFlavorException e) {
+				return false;
+			} catch (IOException e) {
+				return false;
+			}  
+//			JTree tree = (JTree) support.getComponent();
+//			int dropRow = tree.getRowForPath(dl.getPath());
+//			int selRow = tree.getLeadSelectionRow();
+//			if (selRow == dropRow) {
+//				logger.info("Dragging to source");
+//				return false;
+//
+//			}
+			support.setShowDropLocation(true);  
+            return true;  
+        }  
+       
+         protected Transferable createTransferable(JComponent c) {  
+            JTree tree = (JTree)c;  
+            TreePath[] paths = tree.getSelectionPaths();  
+            if(paths != null) {  
+                AbstractIterationStrategyNode node =  
+                    (AbstractIterationStrategyNode)paths[0].getLastPathComponent();  
+                 return new NodeTransferable(node);  
+            }  
+            return null;  
+        }  
+              
+        protected void exportDone(JComponent source, Transferable data, int action) {  
+        }  
+       
+        public int getSourceActions(JComponent c) {  
+            return MOVE;  
+        }  
+       
+        public boolean importData(TransferHandler.TransferSupport support) { 
+            if(!canImport(support)) {
+            	logger.info("Cannot import");
+                return false;  
+            }  
+            // Extract transfer data.  
+            AbstractIterationStrategyNode node = null;  
+            try {  
+                Transferable t = support.getTransferable();  
+                node = (AbstractIterationStrategyNode) t.getTransferData(getNodesFlavor());  
+            } catch(UnsupportedFlavorException ufe) {  
+                logger.error("UnsupportedFlavor", ufe);  
+            } catch (Exception e) {
+            	logger.error("Problem getting transfer data", e);
+            }
+
+           // Get drop location info.  
+            JTree.DropLocation dl =  
+                    (JTree.DropLocation)support.getDropLocation();  
+            int childIndex = dl.getChildIndex();  
+            TreePath dest = dl.getPath();  
+            AbstractIterationStrategyNode parent =  
+                (AbstractIterationStrategyNode)dest.getLastPathComponent();
+            int index = childIndex;
+            logger.info ("parent is a " + parent.getClass().getName());
+            if (parent instanceof NamedInputPortNode) {
+            	AbstractIterationStrategyNode sibling = parent;
+            	parent = (AbstractIterationStrategyNode) sibling.getParent();
+            	index = parent.getIndex(sibling);
+            } else if (index == -1) {
+            	index = parent.getChildCount();
+            }
+            if (parent instanceof TerminalNode) {
+            	if (parent.getChildCount() > 0) {
+            		parent = (AbstractIterationStrategyNode) parent.getChildAt(0);
+            		index = parent.getChildCount();
+            	}
+            	
+            }
+            logger.info("parent is a " + parent.getClass().getName());
+
+			try {
+				// The parent insert removes from the oldParent
+				parent.insert(node, index++);
+				DefaultTreeModel model = IterationStrategyEditor.this
+						.getModel();
+				refreshModel();
+			} catch (IllegalStateException e) {
+				logger.error(e);
+			} catch (IllegalArgumentException e) {
+				logger.error(e);
+			}
+          return true;  
+        }  
+       
+        public String toString() {  
+            return getClass().getName();  
+        }  
+       
+        public class NodeTransferable implements Transferable {  
+            AbstractIterationStrategyNode node;  
+       
+            public NodeTransferable(AbstractIterationStrategyNode node) {  
+                this.node = node;  
+             }  
+       
+            public AbstractIterationStrategyNode getTransferData(DataFlavor flavor)  
+                                     throws UnsupportedFlavorException {  
+                if(!isDataFlavorSupported(flavor))  
+                    throw new UnsupportedFlavorException(flavor);  
+                return node;  
+            }  
+       
+            public DataFlavor[] getTransferDataFlavors() {  
+                return flavors;  
+            }  
+       
+            public boolean isDataFlavorSupported(DataFlavor flavor) {
+            	 return getNodesFlavor().equals(flavor);  
+            }  
+        }  
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/8c4b365e/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/editor/IterationStrategyEditorControl.java
----------------------------------------------------------------------
diff --git a/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/editor/IterationStrategyEditorControl.java b/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/editor/IterationStrategyEditorControl.java
new file mode 100644
index 0000000..c745283
--- /dev/null
+++ b/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/editor/IterationStrategyEditorControl.java
@@ -0,0 +1,439 @@
+/*******************************************************************************
+ * 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
+ ******************************************************************************/
+/**
+ * This file is a component of the Taverna project,
+ * and is licensed under the GNU LGPL.
+ * Copyright Tom Oinn, EMBL-EBI
+ */
+package net.sf.taverna.t2.workbench.iterationstrategy.editor;
+
+import java.awt.event.ActionEvent;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+import javax.swing.BoxLayout;
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JToolBar;
+import javax.swing.SwingConstants;
+import javax.swing.event.TreeSelectionEvent;
+import javax.swing.event.TreeSelectionListener;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.TreePath;
+
+import net.sf.taverna.t2.workbench.icons.WorkbenchIcons;
+import net.sf.taverna.t2.workbench.iterationstrategy.IterationStrategyIcons;
+import net.sf.taverna.t2.workflowmodel.processor.iteration.CrossProduct;
+import net.sf.taverna.t2.workflowmodel.processor.iteration.DotProduct;
+import net.sf.taverna.t2.workflowmodel.processor.iteration.IterationStrategy;
+import net.sf.taverna.t2.workflowmodel.processor.iteration.IterationStrategyNode;
+import net.sf.taverna.t2.workflowmodel.processor.iteration.TerminalNode;
+
+import org.apache.log4j.Logger;
+
+/**
+ * A control panel for the iteration tree editor allowing the user to manipulate
+ * the tree, removing and adding nodes into the tree based on the context.
+ * 
+ * @author Tom Oinn
+ * @author Stian Soiland-Reyes
+ * 
+ */
+@SuppressWarnings("serial")
+public class IterationStrategyEditorControl extends JPanel {
+
+	protected static Set<IterationStrategyNode> descendentsOfNode(
+			IterationStrategyNode node) {
+		Set<IterationStrategyNode> descendants = new HashSet<IterationStrategyNode>();
+		Set<IterationStrategyNode> nodesToVisit = new HashSet<IterationStrategyNode>();
+		Set<IterationStrategyNode> visitedNodes = new HashSet<IterationStrategyNode>();
+
+		// Note: Not added to descendants
+		nodesToVisit.add(node);
+		while (!nodesToVisit.isEmpty()) {
+			// pick the first one
+			IterationStrategyNode visiting = nodesToVisit.iterator().next();
+			visitedNodes.add(visiting);
+			nodesToVisit.remove(visiting);
+
+			// Find new and interesting children
+			List<IterationStrategyNode> children = visiting.getChildren();
+			Set<IterationStrategyNode> newNodes = new HashSet<IterationStrategyNode>(
+					children);
+			newNodes.removeAll(visitedNodes);
+
+			descendants.addAll(newNodes);
+			nodesToVisit.addAll(newNodes);
+		}
+		return descendants;
+	}
+
+	private static Logger logger = Logger
+			.getLogger(IterationStrategyEditorControl.class);
+
+	private IterationStrategyNode selectedNode = null;
+
+	private IterationStrategyTree tree;
+
+	protected AddCrossAction addCross = new AddCrossAction();
+	protected AddDotAction addDot = new AddDotAction();
+	protected ChangeAction change = new ChangeAction();
+	protected NormalizeAction normalize = new NormalizeAction();
+	protected RemoveAction remove = new RemoveAction();
+	protected MoveUpAction moveUp = new MoveUpAction();
+
+	//private static final int ICON_SIZE = 15;
+
+	protected ImageIcon arrowUpIcon = WorkbenchIcons.upArrowIcon;
+	protected ImageIcon arrowDownIcon = WorkbenchIcons.downArrowIcon;
+	//protected ImageIcon arrowLeft = WorkbenchIcons.leftArrowIcon;
+	//protected ImageIcon arrowRight = WorkbenchIcons.rightArrowIcon;
+	protected ImageIcon normalizeIcon = WorkbenchIcons.normalizeIcon;
+
+	private final IterationStrategy strategy;
+
+	/**
+	 * Create a new panel from the supplied iteration strategy
+	 */
+	public IterationStrategyEditorControl(IterationStrategy strategy) {
+
+		this.strategy = strategy;
+		setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
+
+		// Create the components
+		tree = new IterationStrategyEditor(strategy);
+
+		JButton addCrossButton = new JButton(addCross);
+		addCrossButton.setHorizontalAlignment(SwingConstants.LEFT);
+		JButton addDotButton = new JButton(addDot);
+		addDotButton.setHorizontalAlignment(SwingConstants.LEFT);
+		JButton normalizeButton = new JButton(normalize);
+		normalizeButton.setHorizontalAlignment(SwingConstants.LEFT);
+		normalizeButton.setIcon(normalizeIcon);
+		JButton removeButton = new JButton(remove);
+		removeButton.setHorizontalAlignment(SwingConstants.LEFT);
+		JButton changeButton = new JButton(change);
+		changeButton.setHorizontalAlignment(SwingConstants.LEFT);
+
+		JButton moveUpButton = new JButton(moveUp);
+		moveUpButton.setIcon(arrowUpIcon);
+		moveUpButton.setHorizontalAlignment(SwingConstants.LEFT);
+
+		// Set the default enabled state to off on all buttons other than the
+		// normalizeButton
+		// one.
+		disableButtons();
+
+		// Create a layout with the tree on the right and the buttons in a grid
+		// layout on the left
+		JToolBar toolbar = new JToolBar();
+		toolbar.setFloatable(false);
+		toolbar.setRollover(true);
+		// toolbar.setLayout(new GridLayout(2,2));
+		toolbar.add(normalizeButton);
+		toolbar.add(addCrossButton);
+		toolbar.add(addDotButton);
+		toolbar.add(removeButton);
+		toolbar.add(changeButton);
+		toolbar.add(moveUpButton);
+
+		toolbar.setAlignmentX(LEFT_ALIGNMENT);
+
+		// Listen to tree selection events and enable buttons appropriately
+		tree.addTreeSelectionListener(new ButtonEnabler());
+
+		// Add components to the control panel
+		add(toolbar);
+		JScrollPane treePane = new JScrollPane(tree);
+		//treePane.setPreferredSize(new Dimension(0, 0));
+		add(treePane);
+	}
+
+	public void setIterationStrategy(IterationStrategy iterationStrategy) {
+		tree.setIterationStrategy(iterationStrategy);
+		disableButtons();
+		selectNode(null);
+	}
+
+	private void disableButtons() {
+		remove.setEnabled(false);
+		addCross.setEnabled(false);
+		addDot.setEnabled(false);
+		change.setEnabled(false);
+	}
+
+	private IterationStrategyNode findRoot() {
+		IterationStrategyNode root = (IterationStrategyNode) tree.getModel()
+				.getRoot();
+		if (root.getChildCount() > 0) {
+			return root.getChildAt(0);
+		}
+		return root;
+	}
+
+	protected void selectNode(TreeNode newNode) {
+		DefaultTreeModel model = tree.getModel();
+		if (newNode == null) {
+			newNode = (TreeNode) model.getRoot();
+		}
+		TreeNode[] pathToRoot = model.getPathToRoot(newNode);
+		tree.setSelectionPath(new TreePath(pathToRoot));
+	}
+
+	/**
+	 * Add a cross product node as a child of the selected node
+	 */
+	protected class AddCrossAction extends AbstractAction {
+
+		public AddCrossAction() {
+			super("Add Cross", IterationStrategyIcons.joinIteratorIcon);
+		}
+
+		public void actionPerformed(ActionEvent e) {
+			CrossProduct newNode = new CrossProduct();
+			newNode.setParent(selectedNode);
+			tree.refreshModel();
+		}
+	}
+
+	/**
+	 * Add a dot product node as a child of the selected node
+	 * 
+	 * @author Stian Soiland-Reyes
+	 * 
+	 */
+	protected class AddDotAction extends AbstractAction {
+
+		public AddDotAction() {
+			super("Add Dot", IterationStrategyIcons.lockStepIteratorIcon);
+		}
+
+		public void actionPerformed(ActionEvent e) {
+			DotProduct newNode = new DotProduct();
+			newNode.setParent(selectedNode);
+			tree.refreshModel();
+		}
+	}
+
+	protected class ButtonEnabler implements TreeSelectionListener {
+		public void valueChanged(TreeSelectionEvent e) {
+			TreePath selectedPath = e.getPath();
+			IterationStrategyNode selectedObject = (IterationStrategyNode) selectedPath
+					.getLastPathComponent();
+			selectedNode = selectedObject;
+			if (selectedObject instanceof CrossProduct
+					|| selectedObject instanceof DotProduct) {
+				if ((selectedObject.getParent() == null) || (selectedObject.getParent() instanceof TerminalNode)) {
+					remove.setEnabled(false);
+				} else {
+					remove.setEnabled(true);
+				}
+				if (selectedObject instanceof CrossProduct) {
+					change.putValue(Action.NAME, "Change to Dot Product");
+					change.putValue(Action.SMALL_ICON,
+							IterationStrategyIcons.lockStepIteratorIcon);
+				} else {
+					change.putValue(Action.NAME, "Change to Cross Product");
+					change.putValue(Action.SMALL_ICON,
+							IterationStrategyIcons.joinIteratorIcon);
+				}
+				addCross.setEnabled(true);
+				addDot.setEnabled(true);
+				change.setEnabled(true);
+			} else {
+				// Top- or leaf node
+				remove.setEnabled(false);
+				addCross.setEnabled(false);
+				addDot.setEnabled(false);
+				change.setEnabled(false);
+			}
+		}
+	}
+
+	/**
+	 * Add a cross product node as a child of the selected node
+	 */
+	protected class ChangeAction extends AbstractAction {
+
+		public ChangeAction() {
+			super("Switch to...", IterationStrategyIcons.joinIteratorIcon);
+		}
+
+		public void actionPerformed(ActionEvent e) {
+			IterationStrategyNode newNode;
+			if (selectedNode instanceof CrossProduct) {
+				newNode = new DotProduct();
+			} else {
+				newNode = new CrossProduct();
+			}
+
+			List<IterationStrategyNode> children = new ArrayList<IterationStrategyNode>(
+					selectedNode.getChildren());
+			for (IterationStrategyNode child : children) {
+				child.setParent(newNode);
+			}
+
+			DefaultTreeModel model = tree.getModel();
+			if (selectedNode.getParent() == null) {
+				model.setRoot(newNode);
+				tree.refreshModel();
+				newNode.setParent(null);
+			} else {
+				IterationStrategyNode parent = selectedNode.getParent();
+				int index = parent.getIndex(selectedNode);
+				selectedNode.setParent(null);
+				parent.insert(newNode, index);
+				tree.refreshModel();
+			}
+
+			selectNode(newNode);
+		}
+
+	}
+
+	/**
+	 * Normalize the tree when the button is pressed
+	 * 
+	 */
+	protected class NormalizeAction extends AbstractAction {
+		public NormalizeAction() {
+			super("Normalize", normalizeIcon);
+		}
+
+		public void actionPerformed(ActionEvent e) {
+			strategy.normalize();
+			// Expand all the nodes in the tree
+			//DefaultTreeModel model = tree.getModel();
+			tree.refreshModel();
+		}
+	}
+
+	/**
+	 * Remove the selected node, moving any descendant leaf nodes to the parent
+	 * to prevent them getting lost
+	 */
+	protected class RemoveAction extends AbstractAction {
+		public RemoveAction() {
+			super("Remove node", WorkbenchIcons.deleteIcon);
+		}
+
+		public void actionPerformed(ActionEvent e) {
+			IterationStrategyNode nodeToBeRemoved = selectedNode;
+
+			//DefaultTreeModel model = tree.getModel();
+
+			// Now removeButton the candidate nodes from their parents and
+			// put them back into the root node
+			IterationStrategyNode root = findRoot();
+			if (root == selectedNode) {
+				return;
+			}
+			IterationStrategyNode oldParent = nodeToBeRemoved.getParent();
+
+			for (IterationStrategyNode nodeToMove : descendentsOfNode(nodeToBeRemoved)) {
+				nodeToMove.setParent(oldParent);
+			}
+			nodeToBeRemoved.setParent(null);
+			tree.refreshModel();
+			// Disable the various buttons, as the current selection
+			// is now invalid.
+			remove.setEnabled(false);
+			addCross.setEnabled(false);
+			addDot.setEnabled(false);
+			change.setEnabled(false);
+			selectNode(oldParent);
+		}
+	}
+
+	protected class MoveUpAction extends AbstractAction {
+
+		public MoveUpAction() {
+			super("Move up", arrowUpIcon);
+		}
+
+		public void actionPerformed(ActionEvent e) {
+			//DefaultTreeModel model = tree.getModel();
+
+			IterationStrategyNode aboveNode = aboveSelectedNode();
+			if ((aboveNode == null) || ((aboveNode instanceof TerminalNode) && (aboveNode.getChildCount() > 0))) {
+				logger.warn("Can't move above top");
+				return;
+			}
+			IterationStrategyNode selectedParent = selectedNode.getParent();
+			IterationStrategyNode aboveParent = aboveNode.getParent();
+			if (selectedParent != null && selectedParent.equals(aboveParent)) {
+				// Siblings
+				int aboveChildIndex = selectedParent.getIndex(aboveNode);
+				selectedParent.insert(selectedNode, aboveChildIndex);
+				tree.refreshModel();
+				selectNode(selectedNode);
+			} else if (aboveNode.equals(selectedParent)) {
+				if (aboveParent instanceof TerminalNode
+						&& selectedNode.getAllowsChildren()) {
+					aboveNode.setParent(selectedNode);
+					selectedNode.setParent(aboveParent);
+					tree.refreshModel();
+					selectNode(selectedNode);
+				} else if (!(aboveParent instanceof TerminalNode)){
+					int aboveChildIndex = aboveParent.getIndex(aboveNode);
+					aboveParent.insert(selectedNode, aboveChildIndex);
+					tree.refreshModel();
+					selectNode(selectedNode);
+				}
+			} else {
+
+			}
+
+		}
+
+	}
+
+	protected IterationStrategyNode belowSelectedNode() {
+		return offsetFromSelectedNode(1);
+	}
+
+	protected IterationStrategyNode offsetFromSelectedNode(int offset) {
+		int currentRow = tree.getRowForPath(tree.getSelectionPath());
+		int offsetRow = currentRow + offset;
+		TreePath offsetPath = tree.getPathForRow(offsetRow);
+		if (offsetPath == null) {
+			return null;
+		}
+		IterationStrategyNode offsetNode = (IterationStrategyNode) offsetPath
+				.getLastPathComponent();
+		if (offsetNode == tree.getModel().getRoot()) {
+			return null;
+		}
+		return offsetNode;
+	}
+
+	protected IterationStrategyNode aboveSelectedNode() {
+		return offsetFromSelectedNode(-1);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/8c4b365e/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/editor/IterationStrategyTree.java
----------------------------------------------------------------------
diff --git a/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/editor/IterationStrategyTree.java b/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/editor/IterationStrategyTree.java
new file mode 100644
index 0000000..c4665c6
--- /dev/null
+++ b/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/editor/IterationStrategyTree.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * 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.iterationstrategy.editor;
+
+import java.util.Enumeration;
+
+import javax.swing.ImageIcon;
+import javax.swing.JTree;
+import javax.swing.tree.DefaultMutableTreeNode;
+import javax.swing.tree.DefaultTreeModel;
+import javax.swing.tree.TreeModel;
+import javax.swing.tree.TreeNode;
+import javax.swing.tree.TreePath;
+import javax.swing.tree.TreeSelectionModel;
+
+import net.sf.taverna.t2.workbench.iterationstrategy.IterationStrategyIcons;
+import net.sf.taverna.t2.workbench.ui.zaria.UIComponentSPI;
+import net.sf.taverna.t2.workflowmodel.processor.iteration.IterationStrategy;
+
+@SuppressWarnings("serial")
+public class IterationStrategyTree extends JTree implements UIComponentSPI {
+
+	private IterationStrategy strategy = null;
+
+	public IterationStrategyTree() {
+		super();
+		setCellRenderer(new IterationStrategyCellRenderer());
+	}
+
+	public ImageIcon getIcon() {
+		return IterationStrategyIcons.leafnodeicon;
+	}
+
+	public void onDisplay() {
+		// TODO Auto-generated method stub
+
+	}
+
+	public void onDispose() {
+		this.strategy = null;
+		setModel(null);
+	}
+
+	public synchronized void setIterationStrategy(
+			IterationStrategy theStrategy) {
+		if (theStrategy != this.strategy) {
+			this.strategy = theStrategy;
+			TreeNode terminal = theStrategy.getTerminalNode();
+			setModel(new DefaultTreeModel(terminal));
+			this.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
+			expandTree();
+			revalidate();
+		}
+	}
+	
+	protected synchronized void refreshModel() {
+		this.getModel().nodeStructureChanged(strategy.getTerminalNode());
+		expandTree();
+	}
+
+	@Override
+	public DefaultTreeModel getModel() {
+		return (DefaultTreeModel) super.getModel();
+	}
+
+	@Override
+	public void setModel(TreeModel newModel) {
+		if (newModel != null && !(newModel instanceof DefaultTreeModel)) {
+			throw new IllegalArgumentException(
+					"Model must be a DefaultTreeModel");
+		}
+		super.setModel(newModel);
+	}
+
+	protected void expandTree() {  
+		DefaultMutableTreeNode root =  
+	        (DefaultMutableTreeNode)this.getModel().getRoot();  
+	    Enumeration e = root.breadthFirstEnumeration();  
+	    while(e.hasMoreElements()) {  
+	        DefaultMutableTreeNode node =  
+	            (DefaultMutableTreeNode)e.nextElement();  
+	        if(node.isLeaf()) continue;  
+	        int row = this.getRowForPath(new TreePath(node.getPath()));  
+	        this.expandRow(row);  
+	    }  
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/8c4b365e/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/menu/IterationStrategyConfigureMenuAction.java
----------------------------------------------------------------------
diff --git a/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/menu/IterationStrategyConfigureMenuAction.java b/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/menu/IterationStrategyConfigureMenuAction.java
new file mode 100644
index 0000000..f8c7f73
--- /dev/null
+++ b/taverna-workbench-iteration-strategy-ui/src/main/java/net/sf/taverna/t2/workbench/iterationstrategy/menu/IterationStrategyConfigureMenuAction.java
@@ -0,0 +1,65 @@
+/**********************************************************************
+ * Copyright (C) 2007-2009 The University of Manchester   
+ * 
+ *  Modifications to the initial code base are copyright of their
+ *  respective authors, or their employers as appropriate.
+ * 
+ *  This program is free software; you can redistribute it and/or
+ *  modify it under the terms of the GNU Lesser General Public License
+ *  as published by the Free Software Foundation; either version 2.1 of
+ *  the License, or (at your option) any later version.
+ *    
+ *  This program is distributed in the hope that it will be useful, but
+ *  WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ *  Lesser General Public License for more details.
+ *    
+ *  You should have received a copy of the GNU Lesser General Public
+ *  License along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ **********************************************************************/
+package net.sf.taverna.t2.workbench.iterationstrategy.menu;
+
+import java.awt.event.ActionEvent;
+import java.net.URI;
+
+import javax.swing.AbstractAction;
+import javax.swing.Action;
+
+import net.sf.taverna.t2.ui.menu.AbstractContextualMenuAction;
+import net.sf.taverna.t2.workbench.helper.HelpEnabledDialog;
+import net.sf.taverna.t2.workbench.iterationstrategy.contextview.IterationStrategyConfigurationDialog;
+import net.sf.taverna.t2.workbench.iterationstrategy.contextview.IterationStrategyContextualView;
+import net.sf.taverna.t2.workflowmodel.Processor;
+
+public class IterationStrategyConfigureMenuAction extends AbstractContextualMenuAction {
+	
+	
+	
+	public static final URI configureRunningSection = URI
+	.create("http://taverna.sf.net/2009/contextMenu/configureRunning");
+	
+	private static final URI ITERATION_STRATEGY_CONFIGURE_URI = URI
+	.create("http://taverna.sf.net/2008/t2workbench/iterationStrategyConfigure");
+
+	public IterationStrategyConfigureMenuAction() {
+		super(configureRunningSection, 40, ITERATION_STRATEGY_CONFIGURE_URI);
+	}
+
+	@SuppressWarnings("serial")
+	@Override
+	protected Action createAction() {
+		return new AbstractAction("List handling...") {
+			public void actionPerformed(ActionEvent e) {
+				Processor p = (Processor) getContextualSelection().getSelection();
+				final HelpEnabledDialog dialog = new IterationStrategyConfigurationDialog(null, p, IterationStrategyContextualView.copyIterationStrategyStack(p.getIterationStrategy()));		
+				dialog.setVisible(true);
+			}
+		};
+	}
+	
+	public boolean isEnabled() {
+		return super.isEnabled() && (getContextualSelection().getSelection() instanceof Processor);
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/8c4b365e/taverna-workbench-iteration-strategy-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent
----------------------------------------------------------------------
diff --git a/taverna-workbench-iteration-strategy-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent b/taverna-workbench-iteration-strategy-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent
new file mode 100644
index 0000000..6f25f4e
--- /dev/null
+++ b/taverna-workbench-iteration-strategy-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent
@@ -0,0 +1 @@
+net.sf.taverna.t2.workbench.iterationstrategy.menu.IterationStrategyConfigureMenuAction
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/8c4b365e/taverna-workbench-iteration-strategy-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.views.contextualviews.activity.ContextualViewFactory
----------------------------------------------------------------------
diff --git a/taverna-workbench-iteration-strategy-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.views.contextualviews.activity.ContextualViewFactory b/taverna-workbench-iteration-strategy-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.views.contextualviews.activity.ContextualViewFactory
new file mode 100644
index 0000000..a6a27b0
--- /dev/null
+++ b/taverna-workbench-iteration-strategy-ui/src/main/resources/META-INF/services/net.sf.taverna.t2.workbench.ui.views.contextualviews.activity.ContextualViewFactory
@@ -0,0 +1 @@
+net.sf.taverna.t2.workbench.iterationstrategy.contextview.IterationStrategyContextualViewFactory