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

[32/51] [partial] incubator-taverna-workbench git commit: all packages are moved to org.apache.taverna.*

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/CredentialManagerUILauncher.java
----------------------------------------------------------------------
diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/CredentialManagerUILauncher.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/CredentialManagerUILauncher.java
new file mode 100644
index 0000000..e500281
--- /dev/null
+++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/CredentialManagerUILauncher.java
@@ -0,0 +1,95 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.ui.credentialmanager;
+
+import static java.awt.BorderLayout.CENTER;
+import static javax.swing.SwingUtilities.invokeLater;
+
+import java.awt.Dimension;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+/**
+ * Test launcher for Credential Manager GUI (so it does not have to be
+ * launched from Taverna).
+ *
+ * @author Alexandra Nenadic
+ */
+public class CredentialManagerUILauncher extends JFrame {
+	private static final long serialVersionUID = 2079805060170251148L;
+
+	private final ImageIcon launchCMIcon = new ImageIcon(
+			CredentialManagerUILauncher.class
+					.getResource("/images/cred_manager.png"));
+
+	public CredentialManagerUILauncher() {
+		JPanel jpLaunch = new JPanel();
+		jpLaunch.setPreferredSize(new Dimension(300, 120));
+
+		JLabel jlLaunch = new JLabel("T2: Launch Credential Manager GUI");
+
+		JButton jbLaunch = new JButton();
+		jbLaunch.setIcon(launchCMIcon);
+		jbLaunch.setToolTipText("Launches Credential Manager");
+		jbLaunch.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent e) {
+				CredentialManagerUI cmGUI = new CredentialManagerUI(null, null);
+				if (cmGUI != null)
+					cmGUI.setVisible(true);
+			}
+		});
+
+		jpLaunch.add(jlLaunch);
+		jpLaunch.add(jbLaunch);
+
+		getContentPane().add(jpLaunch, CENTER);
+
+		// Handle application close
+		setDefaultCloseOperation(EXIT_ON_CLOSE);
+
+		pack();
+
+        // Centre the frame in the centre of the desktop
+        setLocationRelativeTo(null);
+        // Set the frame's title
+        setTitle("Credential Manager GUI Launcher");
+        setVisible(true);
+	}
+
+	/**
+	 * Launcher for the Credential Manager GUI.
+	 */
+	public static void main(String[] args) {
+        // Create and show GUI on the event handler thread
+        invokeLater(new Runnable(){
+        	@Override
+        	public void run() {
+        		new CredentialManagerUILauncher();
+        	}
+        });
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/CryptoFileFilter.java
----------------------------------------------------------------------
diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/CryptoFileFilter.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/CryptoFileFilter.java
new file mode 100644
index 0000000..e26b3f2
--- /dev/null
+++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/CryptoFileFilter.java
@@ -0,0 +1,72 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.ui.credentialmanager;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+
+import javax.swing.filechooser.FileFilter;
+
+/**
+ * File filter for filtering against various file extensions. Crypto files
+ * normally contain a private key (and optionally its certificate chain) or a
+ * public key certificate (and optionally its certificate chain).
+ * 
+ * .p12 or .pfx are PKCS #12 keystore files containing private key and its
+ * public key (+cert chain); .pem are ASN.1 PEM-encoded files containing one (or
+ * more concatenated) public key certificate(s); .der are ASN.1 DER-encoded
+ * files containing one public key certificate; .cer are CER-encoded files
+ * containing one ore more DER-encoded certificates; .crt files are either
+ * encoded as binary DER or as ASCII PEM. .p7 and .p7c are PKCS #7 certificate
+ * chain files (i.e. SignedData structure without data, just certificate(s)).
+ */
+public class CryptoFileFilter extends FileFilter {
+	// Description of the filter
+	private String description;
+
+	// Array of file extensions to filter against
+	private List<String> exts;
+
+	public CryptoFileFilter(String[] extList, String desc) {
+		exts = Arrays.asList(extList);
+		this.description = desc;
+	}
+
+	@Override
+	public boolean accept(File file) {
+		if (file.isDirectory())
+			return true;
+		if (file.isFile())
+			for (String ext : exts)
+				if (file.getName().toLowerCase().endsWith(ext))
+					return true;
+		return false;
+	}
+
+	public void setDescription(String desc) {
+		this.description = desc;
+	}
+
+	@Override
+	public String getDescription() {
+		return this.description;
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/GetMasterPasswordDialog.java
----------------------------------------------------------------------
diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/GetMasterPasswordDialog.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/GetMasterPasswordDialog.java
new file mode 100644
index 0000000..a030c38
--- /dev/null
+++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/GetMasterPasswordDialog.java
@@ -0,0 +1,168 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.ui.credentialmanager;
+
+import static java.awt.BorderLayout.CENTER;
+import static java.awt.BorderLayout.NORTH;
+import static java.awt.BorderLayout.SOUTH;
+import static javax.swing.BoxLayout.Y_AXIS;
+import static javax.swing.JOptionPane.WARNING_MESSAGE;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static org.apache.taverna.workbench.ui.credentialmanager.CMStrings.WARN_TITLE;
+
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.Frame;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+import javax.swing.border.EmptyBorder;
+
+import org.apache.taverna.workbench.helper.NonBlockedHelpEnabledDialog;
+
+/**
+ * Dialog used for getting a master password for Credential Manager from the
+ * users.
+ * 
+ * @author Alex Nenadic
+ */
+@SuppressWarnings("serial")
+public class GetMasterPasswordDialog extends NonBlockedHelpEnabledDialog {
+	/** Password entry field */
+	private JPasswordField passwordField;
+	/** The entered password */
+	private String password = null;
+	/** Text giving user the instructions what to do in the dialog */
+	private String instructions;
+
+	public GetMasterPasswordDialog(String instructions) {
+		super((Frame) null, "Enter master password", true);
+		this.instructions = instructions;
+		initComponents();
+	}
+
+	private void initComponents() {
+		getContentPane().setLayout(new BorderLayout());
+
+		JLabel instructionsLabel = new JLabel(instructions);
+		// instructionsLabel.setFont(new Font(null, Font.PLAIN, 11));
+
+		JPanel instructionsPanel = new JPanel();
+		instructionsPanel.setLayout(new BoxLayout(instructionsPanel, Y_AXIS));
+		instructionsPanel.add(instructionsLabel);
+		instructionsPanel.setBorder(new EmptyBorder(10, 5, 10, 0));
+
+		JLabel passwordLabel = new JLabel("Password");
+		passwordLabel.setBorder(new EmptyBorder(0, 5, 0, 0));
+
+		passwordField = new JPasswordField(15);
+		JPanel passwordPanel = new JPanel(new GridLayout(1, 1, 5, 5));
+		passwordPanel.add(passwordLabel);
+		passwordPanel.add(passwordField);
+
+		JPanel mainPanel = new JPanel(new BorderLayout());
+		mainPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
+		mainPanel.add(instructionsPanel, NORTH);
+		mainPanel.add(passwordPanel, CENTER);
+
+		JButton okButton = new JButton("OK");
+		okButton.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent evt) {
+				okPressed();
+			}
+		});
+
+		JButton cancelButton = new JButton("Cancel");
+		cancelButton.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent evt) {
+				cancelPressed();
+			}
+		});
+		JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
+		buttonsPanel.add(okButton);
+		buttonsPanel.add(cancelButton);
+
+		getContentPane().add(mainPanel, CENTER);
+		getContentPane().add(buttonsPanel, SOUTH);
+
+		addWindowListener(new WindowAdapter() {
+			@Override
+			public void windowClosing(WindowEvent evt) {
+				closeDialog();
+			}
+		});
+
+		setResizable(false);
+		getRootPane().setDefaultButton(okButton);
+		pack();
+	}
+
+	/**
+	 * Get the password entered in the dialog.
+	 */
+	public String getPassword() {
+		return password;
+	}
+
+	/**
+	 * Check that the entered password is not empty and store the entered
+	 * password.
+	 */
+	private boolean checkPassword() {
+		password = new String(passwordField.getPassword());
+
+		if (password.isEmpty()) {
+			showMessageDialog(this, "The password cannot be empty",
+					WARN_TITLE, WARNING_MESSAGE);
+			return false;
+		}
+
+		return true;
+	}
+
+	private void okPressed() {
+		if (checkPassword())
+			closeDialog();
+	}
+
+	private void cancelPressed() {
+		/*
+		 * Set the password to null as it might have changed in the meantime if
+		 * user entered something then cancelled.
+		 */
+		password = null;
+		closeDialog();
+	}
+
+	private void closeDialog() {
+		setVisible(false);
+		dispose();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/GetPasswordDialog.java
----------------------------------------------------------------------
diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/GetPasswordDialog.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/GetPasswordDialog.java
new file mode 100644
index 0000000..d0fa8be
--- /dev/null
+++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/GetPasswordDialog.java
@@ -0,0 +1,167 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.ui.credentialmanager;
+
+import static java.awt.BorderLayout.CENTER;
+import static java.awt.BorderLayout.NORTH;
+import static java.awt.BorderLayout.SOUTH;
+import static java.awt.Font.PLAIN;
+import static javax.swing.JOptionPane.WARNING_MESSAGE;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static org.apache.taverna.workbench.ui.credentialmanager.CMStrings.WARN_TITLE;
+
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+import javax.swing.border.EmptyBorder;
+
+import org.apache.taverna.workbench.helper.NonBlockedHelpEnabledDialog;
+
+/**
+ * A general dialog for entering a password.
+ * 
+ * @author Alex Nenadic
+ */
+@SuppressWarnings("serial")
+public class GetPasswordDialog extends NonBlockedHelpEnabledDialog {
+	/** Instructions for user explaining the purpose of the password */
+	private String instructions = null;
+	/* Password entry password field */
+	private JPasswordField passwordField;
+	/* Stores the password entered */
+	private String password = null;
+
+	public GetPasswordDialog(JFrame parent, String title, boolean modal,
+			String instr) {
+		super(parent, title, modal);
+		instructions = instr;
+		initComponents();
+	}
+
+	public GetPasswordDialog(JDialog parent, String title, boolean modal,
+			String instr) {
+		super(parent, title, modal);
+		instructions = instr;
+		initComponents();
+	}
+
+	private void initComponents() {
+		getContentPane().setLayout(new BorderLayout());
+
+		JLabel passwordLabel = new JLabel("Password");
+		passwordField = new JPasswordField(15);
+
+		JButton okButton = new JButton("OK");
+		okButton.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent evt) {
+				okPressed();
+			}
+		});
+
+		JButton cancelButton = new JButton("Cancel");
+		cancelButton.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent evt) {
+				cancelPressed();
+			}
+		});
+
+		JLabel instructionsLabel; // Instructions
+		if (instructions != null) {
+			instructionsLabel = new JLabel(instructions);
+			instructionsLabel.setFont(new Font(null, PLAIN, 11));
+			instructionsLabel.setBorder(new EmptyBorder(5, 5, 5, 5));
+			getContentPane().add(instructionsLabel, NORTH);
+		}
+        
+        JPanel passwordPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
+        passwordPanel.add(passwordLabel);
+        passwordPanel.add(passwordField);
+        passwordPanel.setBorder(new EmptyBorder(5, 5, 5, 5));
+
+        JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
+        buttonsPanel.add(okButton);
+        buttonsPanel.add(cancelButton);
+
+        getContentPane().add(passwordPanel, CENTER);
+        getContentPane().add(buttonsPanel, SOUTH);
+
+		addWindowListener(new WindowAdapter() {
+			@Override
+			public void windowClosing(WindowEvent evt) {
+				closeDialog();
+			}
+		});
+
+        setResizable(false);
+        getRootPane().setDefaultButton(okButton);
+        pack();
+	}
+
+	/**
+	 * Get the password entered in the dialog.
+	 */
+	public String getPassword() {
+		return password;
+	}
+
+	/**
+	 * Check that the password entered is not empty and store the entered
+	 * password.
+	 */
+	private boolean checkPassword() {
+		password = new String(passwordField.getPassword());
+
+		if (password.isEmpty()) {
+			showMessageDialog(this, "The password cannot be empty",
+					WARN_TITLE, WARNING_MESSAGE);
+			return false;
+		}
+
+		return true;
+	}
+
+	private void okPressed() {
+        if (checkPassword())
+            closeDialog();
+    }
+
+	private void cancelPressed() {
+		password = null;
+		closeDialog();
+	}
+
+	private void closeDialog() {
+		setVisible(false);
+		dispose();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/KeyPairsTableModel.java
----------------------------------------------------------------------
diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/KeyPairsTableModel.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/KeyPairsTableModel.java
new file mode 100644
index 0000000..676a45f
--- /dev/null
+++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/KeyPairsTableModel.java
@@ -0,0 +1,212 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.ui.credentialmanager;
+
+import static javax.swing.JOptionPane.ERROR_MESSAGE;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static org.apache.taverna.security.credentialmanager.CredentialManager.KeystoreType.KEYSTORE;
+import static org.apache.taverna.workbench.ui.credentialmanager.CMStrings.ERROR_TITLE;
+import static org.apache.taverna.workbench.ui.credentialmanager.CredentialManagerUI.KEY_PAIR_ENTRY_TYPE;
+
+import java.util.TreeMap;
+
+import javax.swing.JFrame;
+import javax.swing.table.AbstractTableModel;
+
+import org.apache.taverna.lang.observer.Observable;
+import org.apache.taverna.lang.observer.Observer;
+import org.apache.taverna.security.credentialmanager.CMException;
+import org.apache.taverna.security.credentialmanager.CredentialManager;
+import org.apache.taverna.security.credentialmanager.KeystoreChangedEvent;
+
+import org.apache.log4j.Logger;
+
+/**
+ * The table model used to display the Keystore's key pair entries.
+ *
+ * @author Alex Nenadic
+ */
+@SuppressWarnings("serial")
+public class KeyPairsTableModel extends AbstractTableModel implements Observer<KeystoreChangedEvent> {
+	private static final Logger logger = Logger.getLogger(KeyPairsTableModel.class);
+
+	/** Column names*/
+    private String[] columnNames;
+    /** Table data*/
+    private Object[][] data;
+	private CredentialManager credManager;
+
+    public KeyPairsTableModel(CredentialManager credentialManager) {
+        credManager = credentialManager;
+
+		if (credManager == null) {
+			/* Failed to instantiate Credential Manager - warn the user and exit */
+			String sMessage = "Failed to instantiate Credential Manager. ";
+			logger.error("CM GUI: " + sMessage);
+			showMessageDialog(new JFrame(), sMessage,
+					ERROR_TITLE, ERROR_MESSAGE);
+			return;
+		}
+
+       	data = new Object[0][0];
+        columnNames = new String[] {
+        	"Entry Type", // type of the Keystore entry
+        	"Owner", // owner's common name
+        	"Issuer", // issuer's common name
+        	"Serial Number", // public key certificate's serial number
+        	"Last Modified", // last modified date of the entry
+            "URLs", // the invisible column holding the list of URLs associated with this entry
+            "Alias" // the invisible column holding the actual alias in the Keystore
+        };
+
+		try {
+			load();
+		} catch (CMException cme) {
+			String sMessage = "Failed to load key pairs";
+			logger.error(sMessage, cme);
+			showMessageDialog(new JFrame(), sMessage,
+					ERROR_TITLE, ERROR_MESSAGE);
+			return;
+		}
+
+        // Start observing changes to the Keystore
+        credManager.addObserver(this);
+    }
+
+    /**
+     * Load the table model with the key pair entries from the Keystore.
+     */
+    public void load() throws CMException {
+    	// Place key pair entries' aliases in a tree map to sort them
+    	TreeMap<String, String> sortedAliases = new TreeMap<>();
+
+		for (String alias: credManager.getAliases(KEYSTORE))
+			/*
+			 * We are only interested in key pair entries here.
+			 * 
+			 * Alias for such entries is constructed as
+			 * "keypair#<CERT_SERIAL_NUMBER>#<CERT_COMMON_NAME>" where
+			 */
+			if (alias.startsWith("keypair#"))
+				sortedAliases.put(alias, alias);
+
+		// Create one table row for each key pair entry
+		data = new Object[sortedAliases.size()][7];
+
+		/*
+		 * Iterate through the sorted aliases (if any), retrieving the key pair
+		 * entries and populating the table model
+		 */
+		int iCnt = 0;
+		for (String alias : sortedAliases.values()) {
+			/*
+			 * Populate the type column - it is set with an integer but a custom
+			 * cell renderer will cause a suitable icon to be displayed
+			 */
+			data[iCnt][0] = KEY_PAIR_ENTRY_TYPE;
+
+			/*
+			 * Split the alias string to extract owner, issuer and serial number
+			 * alias =
+			 * "keypair#"<SUBJECT_COMMON_NAME>"#"<ISSUER_COMMON_NAME>"#"<SERIAL_NUMBER>
+			 */
+			String[] aliasComponents = alias.split("#");
+
+			// Populate the owner column extracted from the alias
+			data[iCnt][1] = aliasComponents[1];
+
+			// Populate the issuer column extracted from the alias
+			data[iCnt][2] = aliasComponents[2];
+
+			// Populate the serial number column extracted from the alias
+			data[iCnt][3] = aliasComponents[3];
+
+			// Populate the modified date column ("UBER" keystore type supports creation date)
+			//data[iCnt][4] = credManager.getEntryCreationDate(CredentialManager.KEYSTORE, alias);
+
+			// Populate the invisible URLs list column
+			//data[iCnt][5] = credManager.getServiceURLsForKeyPair(alias);
+
+			// Populate the invisible alias column
+			data[iCnt][6] = alias;
+
+			iCnt++;
+		}
+
+		fireTableDataChanged();
+    }
+
+	/**
+	 * Get the number of columns in the table.
+	 */
+	@Override
+	public int getColumnCount() {
+		return columnNames.length;
+	}
+
+	/**
+	 * Get the number of rows in the table.
+	 */
+	@Override
+	public int getRowCount() {
+		return data.length;
+	}
+
+	/**
+	 * Get the name of the column at the given position.
+	 */
+	@Override
+	public String getColumnName(int iCol) {
+		return columnNames[iCol];
+	}
+
+	/**
+	 * Get the cell value at the given row and column position.
+	 */
+	@Override
+	public Object getValueAt(int iRow, int iCol) {
+		return data[iRow][iCol];
+	}
+
+	/**
+	 * Get the class at of the cells at the given column position.
+	 */
+	@Override
+	public Class<? extends Object> getColumnClass(int iCol) {
+		return getValueAt(0, iCol).getClass();
+	}
+
+	/**
+	 * Is the cell at the given row and column position editable?
+	 */
+	@Override
+	public boolean isCellEditable(int iRow, int iCol) {
+		// The table is always read-only
+		return false;
+	}
+
+	@Override
+	public void notify(Observable<KeystoreChangedEvent> sender,
+			KeystoreChangedEvent message) throws Exception {
+		// reload the table
+		if (message.keystoreType.equals(KEYSTORE))
+			load();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewEditPasswordEntryDialog.java
----------------------------------------------------------------------
diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewEditPasswordEntryDialog.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewEditPasswordEntryDialog.java
new file mode 100644
index 0000000..829144a
--- /dev/null
+++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewEditPasswordEntryDialog.java
@@ -0,0 +1,396 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.ui.credentialmanager;
+
+import static java.awt.BorderLayout.CENTER;
+import static java.awt.BorderLayout.SOUTH;
+import static java.awt.GridBagConstraints.HORIZONTAL;
+import static java.awt.GridBagConstraints.NONE;
+import static java.awt.GridBagConstraints.WEST;
+import static javax.swing.JOptionPane.ERROR_MESSAGE;
+import static javax.swing.JOptionPane.WARNING_MESSAGE;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static org.apache.taverna.workbench.ui.credentialmanager.CMStrings.ALERT_TITLE;
+import static org.apache.taverna.workbench.ui.credentialmanager.CMStrings.ERROR_TITLE;
+import static org.apache.taverna.workbench.ui.credentialmanager.CMStrings.WARN_TITLE;
+
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.List;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPasswordField;
+import javax.swing.JTextField;
+import javax.swing.JPanel;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.EtchedBorder;
+
+import org.apache.log4j.Logger;
+
+import org.apache.taverna.security.credentialmanager.CMException;
+import org.apache.taverna.security.credentialmanager.CredentialManager;
+import org.apache.taverna.workbench.helper.NonBlockedHelpEnabledDialog;
+
+/**
+ * Dialog used for editing or entering new service URI, username or password for
+ * a password entry.
+ *
+ * @author Alex Nenadic
+ */
+@SuppressWarnings("serial")
+public class NewEditPasswordEntryDialog extends NonBlockedHelpEnabledDialog
+{
+	private static final Logger logger = Logger
+			.getLogger(NewEditPasswordEntryDialog.class);
+	/** 'Edit' mode constant - the dialog is in the 'edit' entry mode */
+	private static final String EDIT_MODE = "EDIT";
+	/** 'New' mode constant - the dialog is in the 'new' entry mode */
+	private static final String NEW_MODE = "NEW";
+
+	/**
+	 * Mode of this dialog - {@link #NEW_MODE} for entering new password entry
+	 * and {@link #EDIT_MODE} for editting an existing password entry
+	 */
+	String mode;
+	/** Service URI field */
+	private JTextField serviceURIField;
+	/** Username field */
+	private JTextField usernameField;
+	/** First password entry field */
+	private JPasswordField passwordField;
+	/** Password confirmation entry field */
+	private JPasswordField passwordConfirmField;
+	/** Stores service URI entered */
+	private URI serviceURI;
+	/** Stores previous service URI for {@link #EDIT_MODE} */
+	private URI serviceURIOld;
+	/** Stores username entered */
+	private String username;
+    /** Stores password entered*/
+    private String password;
+    private CredentialManager credentialManager;
+
+	public NewEditPasswordEntryDialog(JFrame parent, String title,
+			boolean modal, URI currentURI, String currentUsername,
+			String currentPassword, CredentialManager credentialManager) {
+		super(parent, title, modal);
+		serviceURI = currentURI;
+		username = currentUsername;
+		password = currentPassword;
+		this.credentialManager = credentialManager;
+		if (serviceURI == null && username == null && password == null) {
+			// if passed values are all null
+        	mode = NEW_MODE; // dialog is for entering a new password entry
+		} else {
+            mode = EDIT_MODE; // dialog is for editing an existing entry
+            serviceURIOld = currentURI;
+        }
+        initComponents();
+    }
+
+	public NewEditPasswordEntryDialog(JDialog parent, String title,
+			boolean modal, URI currentURI, String currentUsername,
+			String currentPassword, CredentialManager credentialManager) {
+		super(parent, title, modal);
+        serviceURI = currentURI;
+        username = currentUsername;
+        password = currentPassword;
+		this.credentialManager = credentialManager;
+		if (serviceURI == null && username == null && password == null) {
+			// if passed values are all null
+        	mode = NEW_MODE; // dialog is for entering new password entry
+		} else {
+            mode = EDIT_MODE; // dialog is for editing existing entry
+            serviceURIOld = currentURI;
+        }
+        initComponents();
+    }
+
+	private void initComponents() {
+		getContentPane().setLayout(new BorderLayout());
+
+        JLabel serviceURILabel = new JLabel("Service URI");
+        serviceURILabel.setBorder(new EmptyBorder(0,5,0,0));
+
+        JLabel usernameLabel = new JLabel("Username");
+        usernameLabel.setBorder(new EmptyBorder(0,5,0,0));
+
+        JLabel passwordLabel = new JLabel("Password");
+        passwordLabel.setBorder(new EmptyBorder(0,5,0,0));
+
+        JLabel passwordConfirmLabel = new JLabel("Confirm password");
+        passwordConfirmLabel.setBorder(new EmptyBorder(0,5,0,0));
+
+        serviceURIField = new JTextField();
+        //jtfServiceURI.setBorder(new EmptyBorder(0,0,0,5));
+
+        usernameField = new JTextField(15);
+        //jtfUsername.setBorder(new EmptyBorder(0,0,0,5));
+
+        passwordField = new JPasswordField(15);
+        //jpfFirstPassword.setBorder(new EmptyBorder(0,0,0,5));
+
+        passwordConfirmField = new JPasswordField(15);
+        //jpfConfirmPassword.setBorder(new EmptyBorder(0,0,0,5));
+
+        //If in EDIT_MODE - populate the fields with current values
+		if (mode.equals(EDIT_MODE)) {
+			serviceURIField.setText(serviceURI.toASCIIString());
+			usernameField.setText(username);
+			passwordField.setText(password);
+			passwordConfirmField.setText(password);
+		}
+
+		JButton okButton = new JButton("OK");
+		okButton.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent evt) {
+				okPressed();
+			}
+		});
+
+		JButton cancelButton = new JButton("Cancel");
+		cancelButton.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent evt) {
+				cancelPressed();
+			}
+		});
+
+		JPanel passwordPanel = new JPanel(new GridBagLayout());
+
+		GridBagConstraints gbc = new GridBagConstraints();
+		gbc.weighty = 0.0;
+
+		gbc.weightx = 0.0;
+		gbc.gridx = 0;
+		gbc.gridy = 0;
+		gbc.fill = NONE;
+		gbc.anchor = WEST;
+		gbc.insets = new Insets(5, 10, 0, 0);
+        passwordPanel.add(serviceURILabel, gbc);
+
+		gbc.weightx = 1.0;
+		gbc.gridx = 1;
+		gbc.gridy = 0;
+		gbc.fill = HORIZONTAL;
+		gbc.anchor = WEST;
+		gbc.insets = new Insets(5, 10, 0, 5);
+        passwordPanel.add(serviceURIField, gbc);
+
+		gbc.weightx = 0.0;
+		gbc.gridx = 0;
+		gbc.gridy = 1;
+		gbc.fill = NONE;
+		gbc.anchor = WEST;
+		gbc.insets = new Insets(5, 10, 0, 0);
+        passwordPanel.add(usernameLabel, gbc);
+
+		gbc.weightx = 1.0;
+		gbc.gridx = 1;
+		gbc.gridy = 1;
+		gbc.fill = HORIZONTAL;
+		gbc.anchor = WEST;
+		gbc.insets = new Insets(5, 10, 0, 5);
+        passwordPanel.add(usernameField, gbc);
+
+		gbc.weightx = 0.0;
+		gbc.gridx = 0;
+		gbc.gridy = 2;
+		gbc.fill = NONE;
+		gbc.anchor = WEST;
+		gbc.insets = new Insets(5, 10, 0, 0);
+        passwordPanel.add(passwordLabel, gbc);
+
+		gbc.weightx = 1.0;
+		gbc.gridx = 1;
+		gbc.gridy = 2;
+		gbc.fill = HORIZONTAL;
+		gbc.anchor = WEST;
+		gbc.insets = new Insets(5, 10, 0, 5);
+        passwordPanel.add(passwordField, gbc);
+
+		gbc.weightx = 0.0;
+		gbc.gridx = 0;
+		gbc.gridy = 3;
+		gbc.fill = NONE;
+		gbc.anchor = WEST;
+		gbc.insets = new Insets(5, 10, 0, 0);
+        passwordPanel.add(passwordConfirmLabel, gbc);
+
+		gbc.weightx = 1.0;
+		gbc.gridx = 1;
+		gbc.gridy = 3;
+		gbc.fill = HORIZONTAL;
+		gbc.anchor = WEST;
+		gbc.insets = new Insets(5, 10, 0, 5);
+		passwordPanel.add(passwordConfirmField, gbc);
+
+		passwordPanel.setBorder(new CompoundBorder(new EmptyBorder(10, 10, 10,
+				10), new EtchedBorder()));
+
+		JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
+		buttonsPanel.add(okButton);
+		buttonsPanel.add(cancelButton);
+
+		getContentPane().add(passwordPanel, CENTER);
+		getContentPane().add(buttonsPanel, SOUTH);
+
+		addWindowListener(new WindowAdapter() {
+			@Override
+			public void windowClosing(WindowEvent evt) {
+				closeDialog();
+			}
+		});
+
+        //setResizable(false);
+        getRootPane().setDefaultButton(okButton);
+        pack();
+    }
+
+	/**
+	 * Get the username entered in the dialog.
+	 */
+	public String getUsername() {
+		return username;
+	}
+
+	/**
+	 * Get the service URI entered in the dialog.
+	 */
+	public URI getServiceURI() {
+		return serviceURI;
+	}
+
+	/**
+	 * Get the password entered in the dialog.
+	 */
+	public String getPassword() {
+		return password;
+	}
+
+	/**
+	 * Checks that the user has entered a non-empty service URI, a non-empty
+	 * username, a non-empty password and that an entry with the same URI
+	 * already does not already exist in the Keystore. Store the new password.
+	 */
+	private boolean checkControls() {
+		String serviceURIString = new String(serviceURIField.getText());
+		if (serviceURIString.isEmpty()) {
+			showMessageDialog(this, "Service URI cannot be empty",
+					WARN_TITLE, WARNING_MESSAGE);
+			return false;
+		}
+    	try {
+			serviceURI = new URI(serviceURIString);
+		} catch (URISyntaxException e) {
+			showMessageDialog(this, "Service URI is not a valid URI",
+					WARN_TITLE, WARNING_MESSAGE);
+			return false;
+		}
+
+		username = new String(usernameField.getText());
+		if (username.isEmpty()) {
+			showMessageDialog(this, "Username cannot be empty", WARN_TITLE,
+					WARNING_MESSAGE);
+			return false;
+		}
+
+		String firstPassword = new String(passwordField.getPassword());
+		String confirmPassword = new String(passwordConfirmField.getPassword());
+
+		if (!firstPassword.equals(confirmPassword)) {
+			// passwords do not match
+			showMessageDialog(this, "Passwords do not match", WARN_TITLE,
+					WARNING_MESSAGE);
+			return false;
+		}
+		if (firstPassword.isEmpty()) {
+			// passwords match but are empty
+			showMessageDialog(this, "Password cannot be empty", WARN_TITLE,
+					WARNING_MESSAGE);
+			return false;
+		}
+
+		// passwords the same and non-empty
+		password = firstPassword;
+
+		// Check if the entered service URL is already associated with another password entry in the Keystore
+    	List<URI> uriList = null;
+    	try {
+			uriList = credentialManager.getServiceURIsForAllUsernameAndPasswordPairs();
+		} catch (CMException cme) {
+			// Failed to instantiate Credential Manager - warn the user and exit
+			String exMessage = "Failed to instantiate Credential Manager to check for duplicate service URIs.";
+			logger.error(exMessage, cme);
+			showMessageDialog(new JFrame(), exMessage, ERROR_TITLE,
+					ERROR_MESSAGE);
+			return false;
+		}
+
+       	if (uriList != null) { // should not be null really (although can be empty). Check anyway.
+       		if (mode.equals(EDIT_MODE)) // edit mode
+            	// Remove the current entry's service URI from the list
+                uriList.remove(serviceURIOld);
+
+   			if (uriList.contains(serviceURI)) { // found another entry for this service URI
+        		// Warn the user and exit
+				showMessageDialog(
+						this,
+						"The entered service URI is already associated with another password entry",
+						ALERT_TITLE, WARNING_MESSAGE);
+				return false;
+			}
+		}
+
+		return true;
+	}
+
+	private void okPressed() {
+		if (checkControls())
+			closeDialog();
+	}
+
+	private void cancelPressed() {
+    	// Set all fields to null to indicate that cancel button was pressed
+		serviceURI = null;
+		username = null;
+		password = null;
+		closeDialog();
+	}
+
+	private void closeDialog() {
+		setVisible(false);
+		dispose();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewKeyPairEntryDialog.java
----------------------------------------------------------------------
diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewKeyPairEntryDialog.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewKeyPairEntryDialog.java
new file mode 100644
index 0000000..b2cefa8
--- /dev/null
+++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewKeyPairEntryDialog.java
@@ -0,0 +1,303 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.ui.credentialmanager;
+
+import static java.awt.BorderLayout.CENTER;
+import static java.awt.BorderLayout.SOUTH;
+import static java.awt.BorderLayout.WEST;
+import static java.awt.Font.PLAIN;
+import static javax.swing.BoxLayout.Y_AXIS;
+import static javax.swing.JOptionPane.ERROR_MESSAGE;
+import static javax.swing.JOptionPane.WARNING_MESSAGE;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static javax.swing.ListSelectionModel.SINGLE_SELECTION;
+import static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED;
+import static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED;
+import static org.apache.taverna.workbench.ui.credentialmanager.CMStrings.ALERT_TITLE;
+import static org.apache.taverna.workbench.ui.credentialmanager.CMStrings.ERROR_TITLE;
+
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.security.GeneralSecurityException;
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.border.EmptyBorder;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+import org.apache.taverna.security.credentialmanager.CMException;
+import org.apache.taverna.security.credentialmanager.DistinguishedNameParser;
+import org.apache.taverna.workbench.helper.NonBlockedHelpEnabledDialog;
+
+/**
+ * Allows the user import a key pair from a PKCS #12 file (keystore).
+ */
+@SuppressWarnings("serial")
+class NewKeyPairEntryDialog extends NonBlockedHelpEnabledDialog {
+	//private static final Logger logger = Logger.getLogger(NewKeyPairEntryDialog.class);
+
+	/** List of key pairs available for import */
+	private JList<String> keyPairsJList;
+	/** PKCS #12 keystore */
+	private KeyStore pkcs12KeyStore;
+	/** Private key part of the key pair chosen by the user for import */
+	private Key privateKey;
+	/** Certificate chain part of the key pair chosen by the user for import */
+	private Certificate[] certificateChain;
+	/** Key pair alias to be used for this entry in the Keystore */
+	private String alias;
+	private final DistinguishedNameParser dnParser;
+
+	public NewKeyPairEntryDialog(JFrame parent, String title, boolean modal,
+			KeyStore pkcs12KeyStore, DistinguishedNameParser dnParser)
+			throws CMException {
+		super(parent, title, modal);
+		this.pkcs12KeyStore = pkcs12KeyStore;
+		this.dnParser = dnParser;
+		initComponents();
+	}
+
+	public NewKeyPairEntryDialog(JDialog parent, String title, boolean modal,
+			KeyStore pkcs12KeyStore, DistinguishedNameParser dnParser)
+			throws CMException {
+		super(parent, title, modal);
+		this.pkcs12KeyStore = pkcs12KeyStore;
+		this.dnParser = dnParser;
+		initComponents();
+	}
+
+	/**
+	 * Get the private part of the key pair.
+	 */
+	public Key getPrivateKey() {
+		return privateKey;
+	}
+
+	/**
+	 * Get the certificate chain part of the key pair.
+	 */
+	public Certificate[] getCertificateChain() {
+		return certificateChain;
+	}
+
+	/**
+	 * Get the keystore alias of the key pair.
+	 */
+	public String getAlias() {
+		return alias;
+	}
+
+	private void initComponents() throws CMException {
+		// Instructions
+		JLabel instructionsLabel = new JLabel("Select a key pair to import:");
+		instructionsLabel.setFont(new Font(null, PLAIN, 11));
+		instructionsLabel.setBorder(new EmptyBorder(5, 5, 5, 5));
+		JPanel instructionsPanel = new JPanel(new BorderLayout());
+		instructionsPanel.add(instructionsLabel, WEST);
+
+		// Import button
+		final JButton importButton = new JButton("Import");
+		importButton.setEnabled(false);
+		importButton.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent evt) {
+				importPressed();
+			}
+		});
+
+		// Certificate details button
+		final JButton certificateDetailsButton = new JButton("Details");
+		certificateDetailsButton.setEnabled(false);
+		certificateDetailsButton.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent evt) {
+				certificateDetailsPressed();
+			}
+		});
+
+        // List to hold keystore's key pairs
+		keyPairsJList = new JList<>();
+		keyPairsJList.setSelectionMode(SINGLE_SELECTION);
+		keyPairsJList.addListSelectionListener(new ListSelectionListener() {
+			@Override
+			public void valueChanged(ListSelectionEvent evt) {
+				boolean enabled = keyPairsJList.getSelectedIndex() >= 0;
+				importButton.setEnabled(enabled);
+				certificateDetailsButton.setEnabled(enabled);
+			}
+		});
+
+        // Put the key list into a scroll pane
+		JScrollPane keyPairsScrollPane = new JScrollPane(keyPairsJList,
+				VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED);
+		keyPairsScrollPane.getViewport().setBackground(
+				keyPairsJList.getBackground());
+        
+        JPanel keyPairsPanel = new JPanel();
+        keyPairsPanel.setLayout(new BoxLayout(keyPairsPanel, Y_AXIS));
+		keyPairsPanel.setBorder(new EmptyBorder(10, 10, 10, 10));
+
+		instructionsPanel.setAlignmentY(LEFT_ALIGNMENT);
+		keyPairsPanel.add(instructionsPanel);
+		keyPairsScrollPane.setAlignmentY(LEFT_ALIGNMENT);
+		keyPairsPanel.add(keyPairsScrollPane);
+
+		// Cancel button
+		final JButton cancelButton = new JButton("Cancel");
+		cancelButton.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent evt) {
+				cancelPressed();
+			}
+		});
+
+		JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
+		buttonsPanel.add(certificateDetailsButton);
+		buttonsPanel.add(importButton);
+		buttonsPanel.add(cancelButton);
+
+		getContentPane().setLayout(new BorderLayout());
+		getContentPane().add(keyPairsPanel, CENTER);
+		getContentPane().add(buttonsPanel, SOUTH);
+
+		// Populate the list
+		populateKeyPairList();
+
+		addWindowListener(new WindowAdapter() {
+			@Override
+			public void windowClosing(WindowEvent evt) {
+				closeDialog();
+			}
+		});
+
+		setResizable(false);
+		getRootPane().setDefaultButton(importButton);
+		pack();
+	}
+
+	/**
+	 * Populate the key pair list with the PKCS #12 keystore's key pair aliases.
+	 */
+	private void populateKeyPairList() throws CMException {
+		try {
+			List<String> keyPairAliases = new ArrayList<>();
+
+			Enumeration<String> aliases = pkcs12KeyStore.aliases();
+			while (aliases.hasMoreElements()) {
+				String alias = aliases.nextElement();
+
+				if (pkcs12KeyStore.isKeyEntry(alias)) {
+					pkcs12KeyStore.getKey(alias, new char[] {});
+					Certificate[] certs = pkcs12KeyStore
+							.getCertificateChain(alias);
+					if (certs != null && certs.length != 0)
+						keyPairAliases.add(alias);
+				}
+			}
+
+            if (!keyPairAliases.isEmpty()) {
+                keyPairsJList.setListData(keyPairAliases.toArray(new String[0]));
+                keyPairsJList.setSelectedIndex(0);
+			} else
+                // No key pairs were found - warn the user
+				showMessageDialog(this,
+						"No private key pairs were found in the file",
+						ALERT_TITLE, WARNING_MESSAGE);
+		} catch (GeneralSecurityException ex) {
+            throw new CMException("Problem occured while reading the PKCS #12 file.",
+                ex);
+        }
+    }
+
+	/**
+	 * Display the selected key pair's certificate.
+	 */
+	private void certificateDetailsPressed() {
+		try {
+			String alias = (String) keyPairsJList.getSelectedValue();
+
+			// Convert the certificate object into an X509Certificate object.
+			X509Certificate cert = dnParser.convertCertificate(pkcs12KeyStore
+					.getCertificate(alias));
+
+			ViewCertDetailsDialog viewCertificateDialog = new ViewCertDetailsDialog(
+					this, "Certificate details", true, (X509Certificate) cert,
+					null, dnParser);
+			viewCertificateDialog.setLocationRelativeTo(this);
+			viewCertificateDialog.setVisible(true);
+		} catch (Exception ex) {
+			showMessageDialog(this,
+					"Failed to obtain certificate details to show",
+					ALERT_TITLE, WARNING_MESSAGE);
+			closeDialog();
+		}
+	}
+
+	public void importPressed() {
+		String alias = (String) keyPairsJList.getSelectedValue();
+		try {
+			privateKey = pkcs12KeyStore.getKey(alias, new char[] {});
+			certificateChain = pkcs12KeyStore.getCertificateChain(alias);
+			this.alias = alias;
+		} catch (Exception ex) {
+			showMessageDialog(
+					this,
+					"Failed to load the private key and certificate chain from the PKCS #12 file.",
+					ERROR_TITLE, ERROR_MESSAGE);
+		}
+
+        closeDialog();
+    }
+
+	public void cancelPressed() {
+		/*
+		 * Set everything to null, just in case some of the values have been set
+		 * previously and the user pressed 'cancel' after that.
+		 */
+		privateKey = null;
+		certificateChain = null;
+		closeDialog();
+	}
+
+	private void closeDialog() {
+		setVisible(false);
+		dispose();
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewTrustCertsDialog.java
----------------------------------------------------------------------
diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewTrustCertsDialog.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewTrustCertsDialog.java
new file mode 100644
index 0000000..dc342a1
--- /dev/null
+++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewTrustCertsDialog.java
@@ -0,0 +1,247 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.ui.credentialmanager;
+
+import static java.awt.BorderLayout.CENTER;
+import static java.awt.BorderLayout.SOUTH;
+import static java.awt.BorderLayout.WEST;
+import static java.awt.Font.PLAIN;
+import static javax.security.auth.x500.X500Principal.RFC2253;
+import static javax.swing.BoxLayout.Y_AXIS;
+import static javax.swing.JOptionPane.WARNING_MESSAGE;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static javax.swing.ListSelectionModel.MULTIPLE_INTERVAL_SELECTION;
+import static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED;
+import static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED;
+import static org.apache.taverna.workbench.ui.credentialmanager.CMStrings.ALERT_TITLE;
+
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.EtchedBorder;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+import org.apache.taverna.security.credentialmanager.DistinguishedNameParser;
+import org.apache.taverna.security.credentialmanager.ParsedDistinguishedName;
+import org.apache.taverna.workbench.helper.NonBlockedHelpEnabledDialog;
+
+/**
+ * Allows the user to import one or more trusted certificates from a file.
+ */
+@SuppressWarnings("serial")
+public class NewTrustCertsDialog extends NonBlockedHelpEnabledDialog {
+	private JList<String> trustedCertsJList;
+	/** List of trusted certs read from the file and available for import */
+	private ArrayList<X509Certificate> availableTrustedCerts = new ArrayList<>();
+	/** List of trusted certs selected for import */
+	private ArrayList<X509Certificate> selectedTrustedCerts;
+	private final DistinguishedNameParser dnParser;
+
+	public NewTrustCertsDialog(JFrame parent, String title, boolean modal,
+			ArrayList<X509Certificate> lCerts, DistinguishedNameParser dnParser) {
+		super(parent, title, modal);
+		availableTrustedCerts = lCerts;
+		this.dnParser = dnParser;
+		initComponents();
+	}
+
+	public NewTrustCertsDialog(JDialog parent, String title, boolean modal,
+			ArrayList<X509Certificate> lCerts, DistinguishedNameParser dnParser) {
+		super(parent, title, modal);
+		availableTrustedCerts = lCerts;
+		this.dnParser = dnParser;
+		initComponents();
+	}
+
+	private void initComponents() {
+		// Instructions
+		JLabel instructionsLabel = new JLabel(
+				"Select one or more certificates for import:");
+		instructionsLabel.setFont(new Font(null, PLAIN, 11));
+		instructionsLabel.setBorder(new EmptyBorder(5, 5, 5, 5));
+		JPanel instructionsPanel = new JPanel(new BorderLayout());
+		instructionsPanel.add(instructionsLabel, WEST);
+
+		// Import button
+		final JButton importButton = new JButton("Import");
+		importButton.setEnabled(false);
+		importButton.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent evt) {
+				importPressed();
+			}
+		});
+
+		// Certificate details button
+		final JButton certificateDetailsButton = new JButton(
+				"Certificate Details");
+		certificateDetailsButton.setEnabled(false);
+		certificateDetailsButton.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent evt) {
+				certificateDetailsPressed();
+			}
+		});
+
+		// List with trusted certs' aliases
+		trustedCertsJList = new JList<>();
+		trustedCertsJList.setSelectionMode(MULTIPLE_INTERVAL_SELECTION);
+		trustedCertsJList.addListSelectionListener(new ListSelectionListener() {
+			@Override
+			public void valueChanged(ListSelectionEvent evt) {
+				boolean enabled = trustedCertsJList.getSelectedIndex() >= 0;
+				importButton.setEnabled(enabled);
+				certificateDetailsButton.setEnabled(enabled);
+			}
+		});
+		// Populate the list - get the certificate subjects' CNs
+		ArrayList<String> cns = new ArrayList<>();
+		for (int i = 0; i < availableTrustedCerts.size(); i++) {
+			String subjectDN = ((X509Certificate) availableTrustedCerts.get(i))
+					.getSubjectX500Principal().getName(RFC2253);
+			ParsedDistinguishedName parsedDN = dnParser.parseDN(subjectDN);
+			String subjectCN = parsedDN.getCN();
+			cns.add(i, subjectCN);
+		}
+		trustedCertsJList.setListData(cns.toArray(new String[0]));
+		trustedCertsJList.setSelectedIndex(0);
+
+		// Put the list into a scroll pane
+		JScrollPane trustedCertsScrollPanel = new JScrollPane(
+				trustedCertsJList, VERTICAL_SCROLLBAR_AS_NEEDED,
+				HORIZONTAL_SCROLLBAR_AS_NEEDED);
+		trustedCertsScrollPanel.getViewport().setBackground(
+				trustedCertsJList.getBackground());
+
+		JPanel trustedCertsPanel = new JPanel();
+		trustedCertsPanel.setLayout(new BoxLayout(trustedCertsPanel, Y_AXIS));
+		trustedCertsPanel.setBorder(new CompoundBorder(new CompoundBorder(
+				new EmptyBorder(5, 5, 5, 5), new EtchedBorder()),
+				new EmptyBorder(5, 5, 5, 5)));
+
+		instructionsPanel.setAlignmentY(LEFT_ALIGNMENT);
+		trustedCertsPanel.add(instructionsPanel);
+		trustedCertsScrollPanel.setAlignmentY(LEFT_ALIGNMENT);
+		trustedCertsPanel.add(trustedCertsScrollPanel);
+		certificateDetailsButton.setAlignmentY(RIGHT_ALIGNMENT);
+		trustedCertsPanel.add(certificateDetailsButton);
+
+		// Cancel button
+		final JButton cancelButton = new JButton("Cancel");
+		cancelButton.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent evt) {
+				cancelPressed();
+			}
+		});
+
+		JPanel jpButtons = new JPanel(new FlowLayout(FlowLayout.CENTER));
+		jpButtons.add(importButton);
+		jpButtons.add(cancelButton);
+
+		getContentPane().setLayout(new BorderLayout());
+		getContentPane().add(trustedCertsPanel, CENTER);
+		getContentPane().add(jpButtons, SOUTH);
+
+		addWindowListener(new WindowAdapter() {
+			@Override
+			public void windowClosing(WindowEvent evt) {
+				closeDialog();
+			}
+		});
+
+		setResizable(false);
+		getRootPane().setDefaultButton(importButton);
+		pack();
+	}
+
+	/**
+	 * Shows the selected key pair's certificate.
+	 */
+	private void certificateDetailsPressed() {
+		try {
+			int i = trustedCertsJList.getSelectedIndex();
+
+			X509Certificate cert = (X509Certificate) availableTrustedCerts
+					.get(i);
+
+			ViewCertDetailsDialog viewCertificateDialog = new ViewCertDetailsDialog(
+					this, "Certificate details", true, cert, null, dnParser);
+			viewCertificateDialog.setLocationRelativeTo(this);
+			viewCertificateDialog.setVisible(true);
+		} catch (Exception ex) {
+			showMessageDialog(this,
+					"Failed to obtain certificate details to show",
+					ALERT_TITLE, WARNING_MESSAGE);
+			closeDialog();
+		}
+	}
+
+	/**
+	 * Get the trusted certificates selected for import.
+	 */
+	public ArrayList<X509Certificate> getTrustedCertificates() {
+		return selectedTrustedCerts;
+	}
+
+	/**
+	 * Store the selected trusted certs.
+	 */
+	public void importPressed() {
+		int[] selectedValues = trustedCertsJList.getSelectedIndices();
+		selectedTrustedCerts = new ArrayList<>();
+		for (int i = 0; i < selectedValues.length; i++)
+			selectedTrustedCerts.add(availableTrustedCerts
+					.get(selectedValues[i]));
+		closeDialog();
+	}
+
+	public void cancelPressed() {
+		/*
+		 * Set selectedTrustCerts to null to indicate that user has cancelled
+		 * the import
+		 */
+		selectedTrustedCerts = null;
+		closeDialog();
+	}
+
+	private void closeDialog() {
+		setVisible(false);
+		dispose();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/PasswordsTableModel.java
----------------------------------------------------------------------
diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/PasswordsTableModel.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/PasswordsTableModel.java
new file mode 100644
index 0000000..30af7b1
--- /dev/null
+++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/PasswordsTableModel.java
@@ -0,0 +1,226 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.ui.credentialmanager;
+
+import static javax.swing.JOptionPane.ERROR_MESSAGE;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static org.apache.taverna.security.credentialmanager.CredentialManager.KeystoreType.KEYSTORE;
+import static org.apache.taverna.workbench.ui.credentialmanager.CMStrings.ERROR_TITLE;
+import static org.apache.taverna.workbench.ui.credentialmanager.CredentialManagerUI.PASSWORD_ENTRY_TYPE;
+
+import java.net.URI;
+import java.util.TreeMap;
+
+import javax.swing.JFrame;
+import javax.swing.table.AbstractTableModel;
+
+import org.apache.taverna.lang.observer.Observable;
+import org.apache.taverna.lang.observer.Observer;
+import org.apache.taverna.security.credentialmanager.CMException;
+import org.apache.taverna.security.credentialmanager.CredentialManager;
+import org.apache.taverna.security.credentialmanager.KeystoreChangedEvent;
+import org.apache.taverna.security.credentialmanager.UsernamePassword;
+
+import org.apache.log4j.Logger;
+
+/**
+ * The table model used to display the Keystore's username/password pair
+ * entries.
+ * 
+ * @author Alex Nenadic
+ */
+@SuppressWarnings("serial")
+public class PasswordsTableModel extends AbstractTableModel implements
+		Observer<KeystoreChangedEvent> {
+	private static final Logger logger = Logger
+			.getLogger(PasswordsTableModel.class);
+
+	// Column names
+	private String[] columnNames;
+	// Table data
+	private Object[][] data;
+	private CredentialManager credManager;
+
+	public PasswordsTableModel(CredentialManager credentialManager) {
+		credManager = credentialManager;
+		if (credentialManager == null) {
+			// Failed to instantiate Credential Manager - warn the user and exit
+			String sMessage = "Failed to instantiate Credential Manager. ";
+			logger.error("CM GUI: " + sMessage);
+			showMessageDialog(new JFrame(), sMessage, ERROR_TITLE,
+					ERROR_MESSAGE);
+			return;
+		}
+
+		data = new Object[0][0];
+		columnNames = new String[] { "Entry Type", // type of the Keystore entry
+				"Service URL", // the service url, part of the actual alias in
+								// the Keystore
+				"Username", // username for the service, part of the password
+							// entry in the Keystore
+				"Last Modified", // last modified date of the entry
+				"Password", // the invisible column holding the password value
+							// of the password entry in the Keystore
+				"Alias" // the invisible column holding the Keystore alias of
+						// the entry
+		};
+
+		try {
+			load();
+		} catch (CMException cme) {
+			String sMessage = "Failed to load username and password pairs";
+			logger.error(sMessage);
+			showMessageDialog(new JFrame(), sMessage, ERROR_TITLE,
+					ERROR_MESSAGE);
+			return;
+		}
+
+		// Start observing changes to the Keystore
+		credManager.addObserver(this);
+	}
+
+	/**
+	 * Load the PasswordsTableModel with the password entries from the Keystore.
+	 */
+	public void load() throws CMException {
+		// Place password entries' aliases in a tree map to sort them
+		TreeMap<String, String> aliases = new TreeMap<>();
+
+		for (String alias : credManager.getAliases(KEYSTORE))
+			/*
+			 * We are only interested in username/password entries here. Alias
+			 * for such entries is constructed as "password#"<SERVICE_URL> where
+			 * service URL is the service this username/password pair is to be
+			 * used for.
+			 */
+			if (alias.startsWith("password#"))
+				aliases.put(alias, alias);
+
+		// Create one table row for each password entry
+		data = new Object[aliases.size()][6];
+
+		/*
+		 * Iterate through the sorted aliases, retrieving the password entries
+		 * and populating the table model
+		 */
+		int iCnt = 0;
+		for (String alias : aliases.values()) {
+			/*
+			 * Populate the type column - it is set with an integer but a custom
+			 * cell renderer will cause a suitable icon to be displayed
+			 */
+			data[iCnt][0] = PASSWORD_ENTRY_TYPE;
+
+			/*
+			 * Populate the service URL column as a substring of alias from the
+			 * first occurrence of '#' till the end of the string
+			 */
+			String serviceURL = alias.substring(alias.indexOf('#') + 1);
+			data[iCnt][1] = serviceURL;
+
+			/*
+			 * Get the username and password pair from the Keystore. They are
+			 * returned in a single string in format
+			 * <USERNAME><SEPARATOR_CHARACTER><PASSWORD>
+			 */
+			UsernamePassword usernamePassword = credManager
+					.getUsernameAndPasswordForService(URI.create(serviceURL),
+							false, "");
+			String username = usernamePassword.getUsername();
+			String password = usernamePassword.getPasswordAsString();
+
+			// Populate the username column
+			data[iCnt][2] = username;
+
+			// Populate the last modified date column ("UBER" keystore type
+			// supports creation date)
+			// data[iCnt][3] =
+			// credManager.getEntryCreationDate(CredentialManager.KEYSTORE,
+			// alias);
+
+			// Populate the invisible password column
+			data[iCnt][4] = password;
+
+			// Populate the invisible alias column
+			data[iCnt][5] = alias;
+
+			iCnt++;
+		}
+
+		fireTableDataChanged();
+	}
+
+	/**
+	 * Get the number of columns in the table.
+	 */
+	@Override
+	public int getColumnCount() {
+		return columnNames.length;
+	}
+
+	/**
+	 * Get the number of rows in the table.
+	 */
+	@Override
+	public int getRowCount() {
+		return data.length;
+	}
+
+	/**
+	 * Get the name of the column at the given position.
+	 */
+	@Override
+	public String getColumnName(int iCol) {
+		return columnNames[iCol];
+	}
+
+	/**
+	 * Get the cell value at the given row and column position.
+	 */
+	@Override
+	public Object getValueAt(int iRow, int iCol) {
+		return data[iRow][iCol];
+	}
+
+	/**
+	 * Get the class at of the cells at the given column position.
+	 */
+	@Override
+	public Class<? extends Object> getColumnClass(int iCol) {
+		return getValueAt(0, iCol).getClass();
+	}
+
+	/**
+	 * Is the cell at the given row and column position editable?
+	 */
+	@Override
+	public boolean isCellEditable(int iRow, int iCol) {
+		// The table is always read-only
+		return false;
+	}
+
+	@Override
+	public void notify(Observable<KeystoreChangedEvent> sender,
+			KeystoreChangedEvent message) throws Exception {
+		// reload the table
+		if (message.keystoreType.equals(KEYSTORE))
+			load();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/SetMasterPasswordDialog.java
----------------------------------------------------------------------
diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/SetMasterPasswordDialog.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/SetMasterPasswordDialog.java
new file mode 100644
index 0000000..9fe13a4
--- /dev/null
+++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/SetMasterPasswordDialog.java
@@ -0,0 +1,188 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.ui.credentialmanager;
+
+import static java.awt.BorderLayout.CENTER;
+import static java.awt.BorderLayout.NORTH;
+import static java.awt.BorderLayout.SOUTH;
+import static java.awt.Font.PLAIN;
+import static javax.swing.BoxLayout.Y_AXIS;
+import static javax.swing.JOptionPane.WARNING_MESSAGE;
+import static javax.swing.JOptionPane.showMessageDialog;
+import static org.apache.taverna.workbench.ui.credentialmanager.CMStrings.WARN_TITLE;
+
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.Font;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.EtchedBorder;
+
+import org.apache.taverna.workbench.helper.NonBlockedHelpEnabledDialog;
+
+/**
+ * Dialog used for user to set a master password for Credential Manager.
+ * 
+ * @author Alex Nenadic
+ */
+@SuppressWarnings("serial")
+public class SetMasterPasswordDialog extends NonBlockedHelpEnabledDialog {
+	/** Password entry field */
+	private JPasswordField passwordField;
+	/** Password confirmation entry field */
+	private JPasswordField passwordConfirmField;
+	/** The entered password */
+	private String password = null;
+	/** Instructions for the user */
+	private String instructions;
+
+	public SetMasterPasswordDialog(JFrame parent, String title, boolean modal,
+			String instructions) {
+		super(parent, title, modal);
+		this.instructions = instructions;
+		initComponents();
+	}
+
+	private void initComponents() {
+		getContentPane().setLayout(new BorderLayout());
+
+		JLabel instructionsLabel = new JLabel(instructions);
+		instructionsLabel.setFont(new Font(null, PLAIN, 11));
+
+		JPanel instructionsPanel = new JPanel();
+		instructionsPanel.setLayout(new BoxLayout(instructionsPanel, Y_AXIS));
+		instructionsPanel.add(instructionsLabel);
+		instructionsPanel.setBorder(new EmptyBorder(10, 5, 10, 0));
+
+		JLabel passwordLabel = new JLabel("Master password");
+		passwordLabel.setBorder(new EmptyBorder(0, 5, 0, 0));
+
+		JLabel passwordConfirmLabel = new JLabel("Confirm master password");
+		passwordConfirmLabel.setBorder(new EmptyBorder(0, 5, 0, 0));
+
+		passwordField = new JPasswordField(15);
+		passwordConfirmField = new JPasswordField(15);
+
+		JPanel passwordPanel = new JPanel(new GridLayout(2, 2, 5, 5));
+		passwordPanel.add(passwordLabel);
+		passwordPanel.add(passwordField);
+		passwordPanel.add(passwordConfirmLabel);
+		passwordPanel.add(passwordConfirmField);
+
+		JPanel mainPanel = new JPanel(new BorderLayout());
+		mainPanel.setBorder(new CompoundBorder(new EmptyBorder(10, 10, 10, 10),
+				new EtchedBorder()));
+		mainPanel.add(instructionsPanel, NORTH);
+		mainPanel.add(passwordPanel, CENTER);
+
+		JButton okButton = new JButton("OK");
+		okButton.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent evt) {
+				okPressed();
+			}
+		});
+
+		JButton cancelButton = new JButton("Cancel");
+		cancelButton.addActionListener(new ActionListener() {
+			@Override
+			public void actionPerformed(ActionEvent evt) {
+				cancelPressed();
+			}
+		});
+		JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER));
+		buttonsPanel.add(okButton);
+		buttonsPanel.add(cancelButton);
+
+		getContentPane().add(mainPanel, CENTER);
+		getContentPane().add(buttonsPanel, SOUTH);
+
+		addWindowListener(new WindowAdapter() {
+			@Override
+			public void windowClosing(WindowEvent evt) {
+				closeDialog();
+			}
+		});
+
+		setResizable(false);
+		getRootPane().setDefaultButton(okButton);
+		pack();
+	}
+
+	public String getPassword() {
+		return password;
+	}
+
+	/**
+	 * Check that the user has entered a non-empty password and store the new
+	 * password.
+	 */
+	private boolean checkPassword() {
+		String firstPassword = new String(passwordField.getPassword());
+		String confirmPassword = new String(passwordConfirmField.getPassword());
+
+		if (!firstPassword.equals(confirmPassword)) {
+			showMessageDialog(this, "The passwords do not match", WARN_TITLE,
+					WARNING_MESSAGE);
+			return false;
+		}
+		if (firstPassword.isEmpty()) {
+			// passwords match but are empty
+			showMessageDialog(this, "The password cannot be empty", WARN_TITLE,
+					WARNING_MESSAGE);
+			return false;
+		}
+
+		// passwords match and not empty
+		password = firstPassword;
+		return true;
+	}
+
+	private void okPressed() {
+		if (checkPassword())
+			closeDialog();
+	}
+
+	private void cancelPressed() {
+		/*
+		 * Set the password to null as it might have changed in the meantime if
+		 * user entered something then cancelled.
+		 */
+		password = null;
+		closeDialog();
+	}
+
+	private void closeDialog() {
+		setVisible(false);
+		dispose();
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/TableCellRenderer.java
----------------------------------------------------------------------
diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/TableCellRenderer.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/TableCellRenderer.java
new file mode 100644
index 0000000..ad88ac0
--- /dev/null
+++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/TableCellRenderer.java
@@ -0,0 +1,112 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.ui.credentialmanager;
+
+import static org.apache.taverna.workbench.ui.credentialmanager.CredentialManagerUI.KEY_PAIR_ENTRY_TYPE;
+import static org.apache.taverna.workbench.ui.credentialmanager.CredentialManagerUI.PASSWORD_ENTRY_TYPE;
+import static org.apache.taverna.workbench.ui.credentialmanager.CredentialManagerUI.TRUST_CERT_ENTRY_TYPE;
+
+import java.awt.Component;
+//import java.text.DateFormat;
+//import java.util.Date;
+
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+import javax.swing.JTable;
+import javax.swing.border.EmptyBorder;
+import javax.swing.table.DefaultTableCellRenderer;
+//import net.sf.taverna.t2.workbench.ui.credentialmanager.KeyPairsTableModel;
+//import net.sf.taverna.t2.workbench.ui.credentialmanager.PasswordsTableModel;
+//import net.sf.taverna.t2.workbench.ui.credentialmanager.TrustedCertsTableModel;
+
+/**
+ * Custom cell renderer for the cells of the tables displaying
+ * Keystore/Truststore contents.
+ * 
+ * @author Alex Nenadic
+ */
+public class TableCellRenderer extends DefaultTableCellRenderer {
+	private static final long serialVersionUID = -3983986682794010259L;
+
+	private final ImageIcon passwordEntryIcon = new ImageIcon(
+			TableCellRenderer.class.getResource("/images/table/key_entry.png"));
+	private final ImageIcon keypairEntryIcon = new ImageIcon(
+			TableCellRenderer.class
+					.getResource("/images/table/keypair_entry.png"));
+	private final ImageIcon trustcertEntryIcon = new ImageIcon(
+			TableCellRenderer.class
+					.getResource("/images/table/trustcert_entry.png"));
+
+	/**
+	 * Get the rendered cell for the supplied value and column.
+	 */
+	@Override
+	public Component getTableCellRendererComponent(JTable keyStoreTable,
+			Object value, boolean bIsSelected, boolean bHasFocus, int iRow,
+			int iCol) {
+		JLabel cell = (JLabel) super.getTableCellRendererComponent(
+				keyStoreTable, value, bIsSelected, bHasFocus, iRow, iCol);
+
+		if (value != null) {
+        	// Type column - display an icon representing the type
+			if (iCol == 0)
+				configureTypeColumn(value, cell);
+            // Last Modified column - format date (if date supplied)        
+            /*else if (((keyStoreTable.getModel() instanceof PasswordsTableModel) && (iCol == 3)) || 
+            	((keyStoreTable.getModel() instanceof KeyPairsTableModel) && (iCol == 4))||
+            	((keyStoreTable.getModel() instanceof TrustedCertsTableModel) && (iCol == 4))){
+            	if (value instanceof Date) {
+            		// Include timezone
+            		cell.setText(DateFormat.getDateTimeInstance(DateFormat.MEDIUM,
+            			DateFormat.LONG).format((Date) value));
+            	} else {
+            		cell.setText(value.toString());
+            	}
+            }*/
+            // Other columns - just use their text values
+			else
+				cell.setText(value.toString());
+		}
+
+		cell.setBorder(new EmptyBorder(0, 5, 0, 5));
+		return cell;
+	}
+
+	private void configureTypeColumn(Object value, JLabel cell) {
+		ImageIcon icon = null;
+		// The cell is in the first column of Passwords table
+		if (PASSWORD_ENTRY_TYPE.equals(value)) {
+			icon = passwordEntryIcon; // key (i.e. password) entry image
+		}
+		// The cell is in the first column of Key Pairs table
+		else if (KEY_PAIR_ENTRY_TYPE.equals(value)) {
+			icon = keypairEntryIcon; // key pair entry image
+		}
+		// The cell is in the first column of Trusted Certificates table
+		else if (TRUST_CERT_ENTRY_TYPE.equals(value)) {
+			icon = trustcertEntryIcon; // trust. certificate entry image
+		}
+
+		cell.setIcon(icon);
+		cell.setText("");
+		cell.setVerticalAlignment(CENTER);
+		cell.setHorizontalAlignment(CENTER);
+	}
+}

http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/TableHeaderRenderer.java
----------------------------------------------------------------------
diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/TableHeaderRenderer.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/TableHeaderRenderer.java
new file mode 100644
index 0000000..11d7d3c
--- /dev/null
+++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/TableHeaderRenderer.java
@@ -0,0 +1,94 @@
+/*
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing,
+* software distributed under the License is distributed on an
+* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+* KIND, either express or implied. See the License for the
+* specific language governing permissions and limitations
+* under the License.
+*/
+
+package org.apache.taverna.workbench.ui.credentialmanager;
+
+import static javax.swing.border.BevelBorder.RAISED;
+
+import java.awt.Component;
+
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
+import javax.swing.JTable;
+import javax.swing.border.BevelBorder;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.table.DefaultTableCellRenderer;
+
+/**
+ * Custom cell renderer for the headers of the tables displaying 
+ * the Keystore/Truststore contents.
+ */
+@SuppressWarnings("serial")
+public class TableHeaderRenderer extends DefaultTableCellRenderer {
+	private final ImageIcon entryTypeIcon = new ImageIcon(
+			TableHeaderRenderer.class
+					.getResource("/images/table/entry_heading.png"));
+
+	@Override
+	public Component getTableCellRendererComponent(JTable jtKeyStoreTable,
+			Object value, boolean bIsSelected, boolean bHasFocus, int iRow,
+			int iCol) {
+        // Get header renderer
+        JLabel header = (JLabel) jtKeyStoreTable.getColumnModel().getColumn(iCol).getHeaderRenderer();
+
+        // The entry type header contains an icon for every table
+        if (iCol == 0) {
+            header.setText("");
+            header.setIcon(entryTypeIcon); // entry type icon (header for the first column of the table)
+            header.setHorizontalAlignment(CENTER);
+            header.setVerticalAlignment(CENTER);
+            header.setToolTipText("Entry type");
+        }
+        // All other headers contain text
+        else {
+            header.setText((String) value);
+            header.setHorizontalAlignment(LEFT);
+            
+            // Passwords table
+            if (jtKeyStoreTable.getModel() instanceof PasswordsTableModel){
+                if (iCol == 1) //Service URL column
+					header.setToolTipText("URL of the service username and password will be used for");
+				else if (iCol == 2) // Username column
+					header.setToolTipText("Username for the service");
+			}
+            // Key pairs table
+			else if (jtKeyStoreTable.getModel() instanceof KeyPairsTableModel) {
+				if (iCol == 1) // Owner
+					header.setToolTipText("Certificate's owner");
+				else if (iCol == 2) // Issuer
+					header.setToolTipText("Certificate's issuer");
+				else if (iCol == 3) // Serial number
+					header.setToolTipText("Certificate's serial number");
+            }       
+            // Trusted certs table
+			else if (jtKeyStoreTable.getModel() instanceof TrustedCertsTableModel) {
+				if (iCol == 1) // Owner
+					header.setToolTipText("Certificate's owner");
+				else if (iCol == 2) // Issuer
+					header.setToolTipText("Certificate's issuer");
+				else if (iCol == 3) // Serial number
+					header.setToolTipText("Certificate's serial number");
+            }         
+        }
+		header.setBorder(new CompoundBorder(new BevelBorder(RAISED),
+				new EmptyBorder(0, 5, 0, 5)));
+		return header;
+	}
+}