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;
+       }
+}

Reply via email to