The state as of 28 October 2009, before wsdl security was added.
git-svn-id: https://taverna.googlecode.com/svn/taverna/ui/net.sf.taverna.t2.ui-components/tags/credential-manager-ui-pre-security-2009-10-28@8707 bf327186-88b3-11dd-a302-d386e5130c1c
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..e789797
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>net.sf.taverna.t2</groupId>
+ <artifactId>ui-components</artifactId>
+ <version>0.9</version>
+ </parent>
+ <groupId>net.sf.taverna.t2.ui-components</groupId>
+ <artifactId>credential-manager-ui</artifactId>
+ <version>0.10-SNAPSHOT</version>
+ <name>Credential Manager UI</name>
+ <description>
+ Integrates the Credential Manager into the Workbench
+ </description>
+ <dependencies>
+ <dependency>
+ <groupId>net.sf.taverna.t2.ui-api</groupId>
+ <artifactId>menu-api</artifactId>
+ <version>${t2.ui.api.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>net.sf.taverna.t2.security</groupId>
+ <artifactId>credential-manager</artifactId>
+ <version>0.6.2</version>
+ </dependency>
+ </dependencies>
+ <repositories>
+ <repository>
+ <releases />
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ <id>mygrid-repository</id>
+ <name>myGrid Repository</name>
+ <url>http://www.mygrid.org.uk/maven/repository</url>
+ </repository>
+ </repositories>
+</project>
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/CredentialManagerUI.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/CredentialManagerUI.java
new file mode 100644
index 0000000..78ccd8b
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/CredentialManagerUI.java
@@ -0,0 +1,1585 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager;
+
+import java.awt.BorderLayout;
+//import java.awt.Component;
+//import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.Toolkit;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStreamReader;
+
+import java.security.Key;
+import java.security.KeyStore;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+
+import net.sf.taverna.t2.security.credentialmanager.CMException;
+import net.sf.taverna.t2.security.credentialmanager.CMX509Util;
+import net.sf.taverna.t2.security.credentialmanager.CredentialManager;
+import net.sf.taverna.t2.security.credentialmanager.SetMasterPasswordDialog;
+
+import net.sf.taverna.t2.workbench.ui.credentialmanager.CredentialManagerUI;
+import net.sf.taverna.t2.workbench.ui.credentialmanager.CryptoFileFilter;
+import net.sf.taverna.t2.workbench.ui.credentialmanager.EditKeyPairEntryDialog;
+import net.sf.taverna.t2.workbench.ui.credentialmanager.GetPasswordDialog;
+import net.sf.taverna.t2.workbench.ui.credentialmanager.KeyPairsTableModel;
+import net.sf.taverna.t2.workbench.ui.credentialmanager.NewEditPasswordEntryDialog;
+import net.sf.taverna.t2.workbench.ui.credentialmanager.NewKeyPairEntryDialog;
+import net.sf.taverna.t2.workbench.ui.credentialmanager.NewTrustCertsDialog;
+import net.sf.taverna.t2.workbench.ui.credentialmanager.PasswordsTableModel;
+import net.sf.taverna.t2.workbench.ui.credentialmanager.TableCellRenderer;
+import net.sf.taverna.t2.workbench.ui.credentialmanager.TableHeaderRenderer;
+import net.sf.taverna.t2.workbench.ui.credentialmanager.TrustedCertsTableModel;
+import net.sf.taverna.t2.workbench.ui.credentialmanager.ViewCertDetailsDialog;
+import net.sf.taverna.t2.workbench.ui.credentialmanager.ViewUsernamePasswordEntryDialog;
+
+import org.apache.log4j.Logger;
+import org.bouncycastle.openssl.PEMReader;
+import org.bouncycastle.openssl.PEMWriter;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+import javax.swing.JButton;
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTabbedPane;
+import javax.swing.JTable;
+import javax.swing.WindowConstants;
+import javax.swing.border.EmptyBorder;
+import javax.swing.table.TableColumn;
+
+/**
+ * Provides a UI for the Credential Manager for users to manage their credentials
+ * saved by the Credential Manager in Taverna's Keystore and Trustore. Credentials
+ * include username and passwords pairs, key pairs, proxy key pairs and trusted
+ * certificates of CA's and s.
+ * Credentials are stored in two Bouncy Castle "UBER"-type keystores: the
+ * Keystore (containing passwords and (normal and proxy) key pairs) and the Truststore
+ * (containing trusted certificates).
+ *
+ * @author Alex Nenadic
+ */
+
+@SuppressWarnings("serial")
+public class CredentialManagerUI extends JFrame {
+
+ // Credential Manager UI singleton
+ private static CredentialManagerUI INSTANCE;
+
+ // Logger
+ private static Logger logger = Logger.getLogger(CredentialManagerUI.class);
+
+ // Default tabbed pane width - dictates width of this frame
+ private static final int DEFAULT_FRAME_WIDTH = 600;
+
+ // Default tabbed pane height - dictates height of this frame
+ private static final int DEFAULT_FRAME_HEIGHT = 400;
+
+ // Credential Manager icon (when frame minimised)
+ private static final Image credManagerIconImage = Toolkit.getDefaultToolkit()
+ .createImage(CredentialManagerUI.class.getResource("/images/cred_manager_transparent.png"));
+
+ // Credential Manager - manages all operations on the Keystore and Truststore
+ public static CredentialManager credManager;
+
+ // Keystore tab and table controls
+
+ // Tabbed pane to hold keystore entries tables
+ private JTabbedPane keyStoreTabbedPane;
+
+ // Tab 1: holds passwords table
+ private JPanel passwordsTab = new JPanel(new BorderLayout(10, 10));
+
+ // Tab 1: name
+ public static final String PASSWORDS = "Passwords";
+
+ // Tab 2: holds key pairs (user certificates) table
+ private JPanel keyPairsTab = new JPanel(new BorderLayout(10, 10));
+
+ // Tab 2: name
+ public static final String KEYPAIRS = "Key Pairs";
+
+ // Tab 3: holds key pairs (user certificates) table
+ private JPanel proxiesTab = new JPanel(new BorderLayout(10, 10));
+
+ // Tab 3: name
+ public static final String PROXIES = "Proxies";
+
+ // Tab 4: holds trusted certificates table
+ private JPanel trustedCertificatesTab = new JPanel(new BorderLayout(10, 10));
+
+ // Tab 4: name
+ public static final String TRUSTED_CERTIFICATES = "Trusted Certificates";
+
+ // Tables
+
+ // Password entries' table
+ private JTable passwordsTable;
+
+ // Key Pair entries' table
+ private JTable keyPairsTable;
+
+ // Proxy entries' table
+ private JTable proxiesTable;
+
+ // Trusted Certificate entries' table
+ private JTable trustedCertsTable;
+
+ // Value to place in the Type column for a password entry
+ public static final String PASSWORD_ENTRY_TYPE = "Password";
+
+ // Value to place in the Type column for a key pair entry
+ public static final String KEY_PAIR_ENTRY_TYPE = "Key Pair";
+
+ // Value to place in the Type column for a proxy entry
+ public static final String PROXY_ENTRY_TYPE = "Proxy";
+
+ // Value to place in the Type column for a trusted certificate entry
+ public static final String TRUST_CERT_ENTRY_TYPE = "Trusted Certificate";
+
+
+ /**
+ * Returns a CredentialManagerUI singleton.
+ */
+ public static CredentialManagerUI getInstance(){
+ synchronized (CredentialManagerUI.class) {
+ if (INSTANCE == null)
+ try {
+ INSTANCE = new CredentialManagerUI();
+ } catch (CMException cme) {
+ // Failed to instantiate Credential Manager - warn the user and exit
+ String exMessage = "Failed to instantiate Credential Manager. " + cme.getMessage();
+ logger.error(exMessage);
+ JOptionPane.showMessageDialog(new JFrame(), exMessage,
+ "Credential Manager Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ return INSTANCE;
+ }
+
+ /**
+ * Overrides the ObjectÕs clone method to prevent the singleton object to be
+ * cloned.
+ */
+ @Override
+ public Object clone() throws CloneNotSupportedException {
+ throw new CloneNotSupportedException();
+ }
+
+ /**
+ * Creates a new Credential Manager UI's frame.
+ */
+ private CredentialManagerUI() throws CMException
+ {
+
+ // Instantiate Credential Manager that will perform all
+ // operations on the Keystore and Truststore
+ credManager = CredentialManager.getInstance();
+
+ // Initialise the UI components
+ initComponents();
+ }
+
+ private void initComponents(){
+
+ // Initialise the tabbed pane that contains the tabs with tabular
+ // representations of the Keystore's content.
+ keyStoreTabbedPane = new JTabbedPane();
+ // Initialise the tab containing the table for username/password entries from the
+ // Keystore
+ passwordsTable = initTable(PASSWORDS, passwordsTab);
+ // Initialise the tab containing the table for key pair entries from the
+ // Keystore
+ keyPairsTable = initTable(KEYPAIRS, keyPairsTab);
+ // Initialise the tab containing the table for proxy entries from the
+ // Keystore
+ proxiesTable = initTable(PROXIES, proxiesTab);
+ // Initialise the tab containing the table for trusted certificate
+ // entries from the Truststore
+ trustedCertsTable = initTable(TRUSTED_CERTIFICATES,
+ trustedCertificatesTab);
+ // Set the size of the tabbed pane to the preferred size - the size of
+ // the main application frame depends on it.
+ keyStoreTabbedPane.setPreferredSize(new Dimension(DEFAULT_FRAME_WIDTH,
+ DEFAULT_FRAME_HEIGHT));
+
+ // Button for changing Credential Manager's master password
+ JButton changeMasterPasswordButton = new JButton("Change master password");
+ changeMasterPasswordButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent e) {
+ changeMasterPassword();
+ }});
+ JPanel changeMasterPasswordPanel = new JPanel(new FlowLayout(FlowLayout.RIGHT));
+ changeMasterPasswordPanel.add(changeMasterPasswordButton);
+
+ // Add change master password to the main application frame
+ getContentPane().add(changeMasterPasswordPanel, BorderLayout.NORTH);
+ // Add tabbed pane to the main application frame
+ getContentPane().add(keyStoreTabbedPane, BorderLayout.CENTER);
+
+ // Handle application close
+ addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent evt) {
+ closeFrame();
+ }
+ });
+ setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
+
+ pack();
+
+ // Centre the frame in the centre of the desktop
+ setLocationRelativeTo(null);
+
+ // Set the frame's icon
+ setIconImage(credManagerIconImage);
+
+ // Set the frame's title
+ setTitle("Credential Manager");
+
+ //setModal(true);
+ //setVisible(true);
+ }
+
+ protected void changeMasterPassword() {
+
+ SetMasterPasswordDialog changePasswordDialog = new SetMasterPasswordDialog(this, "Change master password", true , "Change master password for Credential Manager");
+ changePasswordDialog.setLocationRelativeTo(null);
+ changePasswordDialog.setVisible(true);
+ String password = changePasswordDialog.getPassword();
+ if (password == null){ // user cancelled
+ return; // do nothing
+ }
+ else{
+ try {
+ credManager.changeMasterPassword(password);
+ JOptionPane.showMessageDialog(new JFrame(), "Master password changed sucessfully",
+ "Credential Manager Error", JOptionPane.INFORMATION_MESSAGE);
+ } catch (CMException cme) {
+ // Failed to change the master password for Credential Manager - warn the user
+ String exMessage = "Failed to change master password for Credential Manager";
+ logger.error(exMessage);
+ JOptionPane.showMessageDialog(new JFrame(), exMessage,
+ "Credential Manager Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+
+ /**
+ * Initialise the tab on the tabbed pane and its tabular content.
+ */
+ private JTable initTable(String tableType, JPanel tab) {
+
+ JTable table = null;
+
+ if (tableType.equals(PASSWORDS)) { // Passwords table
+ // The Passwords table's data model
+ PasswordsTableModel passwordsTableModel = new PasswordsTableModel();
+ // The table itself
+ table = new JTable(passwordsTableModel);
+
+ // Set the password and alias columns of the Passwords table to be
+ // invisible by removing them from the column model (they will still present
+ // in the table model)
+ // Remove the last column first
+ TableColumn aliasColumn = table.getColumnModel().getColumn(5);
+ table.getColumnModel().removeColumn(aliasColumn);
+ TableColumn passwordColumn = table.getColumnModel().getColumn(4);
+ table.getColumnModel().removeColumn(passwordColumn);
+
+ // Buttons
+ JButton newPasswordButton = new JButton("New");
+ newPasswordButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent e) {
+ newPassword();
+ }});
+ JButton viewPasswordButton = new JButton("Details");
+ viewPasswordButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent e) {
+ viewPassword();
+ }});
+ JButton editPasswordButton = new JButton("Edit");
+ editPasswordButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent e) {
+ editPassword();
+ }});
+ JButton deletePasswordButton = new JButton("Delete");
+ deletePasswordButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent e) {
+ deletePassword();
+ }});
+
+ // Panel to hold the buttons
+ JPanel bp = new JPanel();
+ bp.add(viewPasswordButton);
+ bp.add(editPasswordButton);
+ bp.add(newPasswordButton);
+ bp.add(deletePasswordButton);
+
+ // Add button panel to the tab
+ tab.add(bp, BorderLayout.PAGE_END);
+
+ }
+ else if (tableType.equals(KEYPAIRS)) { // Key Pairs tab
+ // The Key Pairs table's data model
+ KeyPairsTableModel keyPairsTableModel = new KeyPairsTableModel();
+ // The table itself
+ table = new JTable(keyPairsTableModel);
+
+ // Set the alias and service URLs columns of the KayPairs table to be
+ // invisible by removing them from the column model (they will still present
+ // in the table model)
+ // Remove the last column first
+ TableColumn aliasColumn = table.getColumnModel().getColumn(6);
+ table.getColumnModel().removeColumn(aliasColumn);
+ TableColumn serviceURLsColumn = table.getColumnModel().getColumn(5);
+ table.getColumnModel().removeColumn(serviceURLsColumn);
+
+ // Buttons
+ JButton viewKeyPairButton = new JButton("Details");
+ viewKeyPairButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent e) {
+ viewCertificate();
+ }});
+ JButton editServiceURLKeyPairButton = new JButton("Edit");
+ editServiceURLKeyPairButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent e) {
+ editKeyPair();
+ }});
+ JButton importKeyPairButton = new JButton("Import");
+ importKeyPairButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent e) {
+ newKeyPair();
+ }});
+ JButton exportKeyPairButton = new JButton("Export");
+ exportKeyPairButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent e) {
+ exportKeyPair();
+ }});
+ JButton deleteKeyPairButton = new JButton("Delete");
+ deleteKeyPairButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent e) {
+ deleteKeyPair();
+ }});
+
+ // Panel to hold the buttons
+ JPanel bp = new JPanel();
+ bp.add(viewKeyPairButton);
+ bp.add(editServiceURLKeyPairButton);
+ bp.add(importKeyPairButton);
+ bp.add(exportKeyPairButton);
+ bp.add(deleteKeyPairButton);
+
+ // Add button panel to the tab
+ tab.add(bp, BorderLayout.PAGE_END);
+
+ }
+ else if (tableType.equals(PROXIES)) { // Proxies tab
+ // The Proxies table's data model
+ ProxiesTableModel proxiesTableModel = new ProxiesTableModel();
+
+ // The table itself
+ table = new JTable(proxiesTableModel);
+
+ // Set alias column of the Proxies table to be
+ // invisible by removing it from the column model (it will still present
+ // in the table model)
+ TableColumn aliasColumn = table.getColumnModel().getColumn(5);
+ table.getColumnModel().removeColumn(aliasColumn);
+
+ // Buttons
+ JButton viewProxyButton = new JButton("Details");
+ viewProxyButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent e) {
+ viewProxyCertificate();
+ }});
+ JButton deleteProxyButton = new JButton("Delete");
+ deleteProxyButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent e) {
+ deleteProxy();
+ }});
+
+
+ // Panel to hold the buttons
+ JPanel bp = new JPanel();
+ bp.add(viewProxyButton);
+ bp.add(deleteProxyButton);
+
+ // Add button panel to the tab
+ tab.add(bp, BorderLayout.PAGE_END);
+
+ }
+ else if (tableType.equals(TRUSTED_CERTIFICATES)) { // Trusted Certificates tab
+ // The Trusted Certificate table's data model
+ TrustedCertsTableModel trustedCertificatesTableModel = new TrustedCertsTableModel();
+ // The table itself
+ table = new JTable(trustedCertificatesTableModel);
+
+ // Set the alias column of the Trusted Certs table to be invisible
+ // by removing it from the column model (it is still present in the
+ // table model)
+ TableColumn aliasColumn = table.getColumnModel().getColumn(5);
+ table.getColumnModel().removeColumn(aliasColumn);
+
+ // Buttons
+ JButton viewTrustedCertificateButton = new JButton("Details");
+ viewTrustedCertificateButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent e) {
+ viewCertificate();
+ }});
+ JButton importTrustedCertificateButton = new JButton("Import");
+ importTrustedCertificateButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent e) {
+ importTrustedCertificate();
+ }});
+ JButton exportTrustedCertificateButton = new JButton("Export");
+ exportTrustedCertificateButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent e) {
+ exportTrustedCertificate();
+ }});
+ JButton deleteTrustedCertificateButton = new JButton("Delete");
+ deleteTrustedCertificateButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent e) {
+ deleteTrustedCertificate();
+ }});
+
+ // Panel to hold the buttons
+ JPanel bp = new JPanel();
+ bp.add(viewTrustedCertificateButton);
+ bp.add(importTrustedCertificateButton);
+ bp.add(exportTrustedCertificateButton);
+ bp.add(deleteTrustedCertificateButton);
+
+ // Add button panel to the tab
+ tab.add(bp, BorderLayout.PAGE_END);
+ }
+
+ table.setShowGrid(false);
+ table.setRowMargin(0);
+ table.getColumnModel().setColumnMargin(0);
+ table.getTableHeader().setReorderingAllowed(false);
+ table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
+ // Top accommodates entry icons with 2 pixels spare space (images are 16x16 pixels)
+ table.setRowHeight(18);
+
+ // Add custom renderrers for the table headers and cells
+ for (int iCnt = 0; iCnt < table.getColumnCount(); iCnt++) {
+ TableColumn column = table.getColumnModel().getColumn(iCnt);
+ column.setHeaderRenderer(new TableHeaderRenderer());
+ column.setCellRenderer(new TableCellRenderer());
+ }
+
+ // Make the first column small and not resizable (it holds icons to
+ // represent different entry types)
+ TableColumn typeCol = table.getColumnModel().getColumn(0);
+ typeCol.setResizable(false);
+ typeCol.setMinWidth(20);
+ typeCol.setMaxWidth(20);
+ typeCol.setPreferredWidth(20);
+
+ // Set the size for the second column
+ // (i.e. Service URL column of Passwords and Key Pairs tables, and
+ // Certificate Name column of the Trusted Certificates table)
+ TableColumn secondCol = table.getColumnModel().getColumn(1);
+ secondCol.setMinWidth(20);
+ secondCol.setMaxWidth(10000);
+ secondCol.setPreferredWidth(300);
+
+ // Don't care about the size of other columns
+
+ // Put the table into a scroll pane
+ JScrollPane jspTableScrollPane = new JScrollPane(table,
+ JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ jspTableScrollPane.getViewport().setBackground(table.getBackground());
+
+ // Put the scroll pane on the tab panel
+ tab.add(jspTableScrollPane, BorderLayout.CENTER);
+ jspTableScrollPane.setBorder(new EmptyBorder(3, 3, 3, 3));
+
+ // Add mouse listeners to show an entry's details if it is
+ // double-clicked
+ table.addMouseListener(new MouseAdapter() {
+ public void mouseClicked(MouseEvent evt) {
+ tableDoubleClick(evt);
+ }
+ });
+
+ // Add the tab to the tabbed pane
+ keyStoreTabbedPane.addTab(tableType, tab);
+
+ return table;
+ }
+
+ /**
+ * Display the username/password pair entry from the Keystore.
+ */
+ private void viewPassword() {
+ // Which username/password pair entry has been selected, if any?
+ int iRow = passwordsTable.getSelectedRow();
+ if (iRow == -1) { // no row currently selected
+ return;
+ }
+
+ // Get current values for service URL, username and password
+ String serviceURL = (String) passwordsTable.getValueAt(iRow, 1); // current entry's service URL
+
+ String username = (String) passwordsTable.getValueAt(iRow, 2); // current entry's username
+
+ // Because the password column is not visible we call
+ // the getValueAt method on the table model rather than at the JTable
+ String password = (String) passwordsTable.getModel().getValueAt(iRow,4); // current entry's password value
+
+ // Let the user view service URL, username and password of the entry
+ ViewUsernamePasswordEntryDialog viewServicePassDialog = new ViewUsernamePasswordEntryDialog(
+ this, serviceURL, username, password);
+
+ viewServicePassDialog.setLocationRelativeTo(this);
+ viewServicePassDialog.setVisible(true);
+ }
+
+ /**
+ * Insert a new username/password pair for a service URL in the Keystore.
+ */
+ private void newPassword() {
+
+ String serviceURL = null; // service URL
+ String username = null; // username
+ String password = null; // password
+
+ // Loop until the user cancels or enters everything correctly
+ while (true) {
+
+ // Let the user insert a new password entry (by specifying service
+ // URL, username and password)
+ NewEditPasswordEntryDialog newPasswordDialog = new NewEditPasswordEntryDialog(
+ this, "New username and password for a service", true, serviceURL, username,
+ password);
+ newPasswordDialog.setLocationRelativeTo(this);
+ newPasswordDialog.setVisible(true);
+
+ serviceURL = newPasswordDialog.getServiceURL(); // get service URL
+ username = newPasswordDialog.getUsername(); // get username
+ password = newPasswordDialog.getPassword(); // get password
+
+ if (password == null) { // user cancelled - any of the above three fields is null
+ // do nothing
+ return;
+ }
+
+ // Check if a password entry with the given service URL
+ // already exists in the Keystore.
+ // We ask this here as the user may wish to overwrite the
+ // existing password entry.
+ // Checking for key pair entries' URLs is done in the
+ // NewEditPasswordEntry dialog.
+
+ // Get list of service URLs for all the password entries in the Keystore
+ ArrayList<String> serviceURLs = null;
+ try{
+ serviceURLs = credManager.getServiceURLsforUsernameAndPasswords();
+ }
+ catch(CMException cme){
+ String exMessage = "Failed to get service URLs for all username and password pairs to check if the entered service URL already exists";
+ JOptionPane.showMessageDialog(this, exMessage,
+ "Credential Manager Error",
+ JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ if (serviceURLs.contains(serviceURL)) { // if such a URL already exists
+ // Ask if the user wants to overwrite it
+ int iSelected = JOptionPane.showConfirmDialog(this,
+ "The Keystore already contains a password entry with the same service URL.\n"
+ + "Do you want to overwrite it?",
+ "Credential Manager Alert",
+ JOptionPane.YES_NO_OPTION);
+
+ // Add the new password entry in the Keystore
+ if (iSelected == JOptionPane.YES_OPTION) {
+ try{
+ credManager.saveUsernameAndPasswordForService(username, password, serviceURL);
+ break;
+ }
+ catch (CMException cme){
+ String exMessage = "Failed to insert a new username and password pair in the Keystore";
+ JOptionPane.showMessageDialog(this, exMessage,
+ "Credential Manager Error",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ // Otherwise show the same window with the entered service
+ // URL, username and password values
+ }
+ else {
+ // Add the new password entry in the Keystore
+ try{
+ credManager.saveUsernameAndPasswordForService(username, password, serviceURL);
+ break;
+ }
+ catch (CMException cme){
+ String exMessage = "Failed to insert a new username and password pair in the Keystore";
+ JOptionPane.showMessageDialog(this, exMessage,
+ "Credential Manager Error",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+ }
+
+
+ /**
+ * Edit a username and password entry or their related service URL in the Keystore.
+ */
+ private void editPassword() {
+
+ // Which password entry has been selected?
+ int iRow = passwordsTable.getSelectedRow();
+ if (iRow == -1) { // no row currently selected
+ return;
+ }
+
+ // Get current values for service URL, username and password
+ String serviceURL = (String) passwordsTable.getValueAt(iRow, 1); // current entry's service URL
+
+ String username = (String) passwordsTable.getValueAt(iRow, 2); // current entry's username
+
+ // Because the password column is not visible we call
+ // the getValueAt method on the table model rather than at the JTable
+ String password = (String) passwordsTable.getModel().getValueAt(iRow, 4); // current entry's password value
+
+ while (true) { // loop until user cancels or enters everything correctly
+ // Let the user edit service URL, username or password of a password entry
+ NewEditPasswordEntryDialog editPasswordDialog = new NewEditPasswordEntryDialog(
+ this, "Edit username and password for a service", true, serviceURL, username,
+ password);
+
+ editPasswordDialog.setLocationRelativeTo(this);
+ editPasswordDialog.setVisible(true);
+
+ // New values
+ String nServiceURL = editPasswordDialog.getServiceURL(); // get new service URL
+ String nUsername = editPasswordDialog.getUsername(); // get new username
+ String nPassword = editPasswordDialog.getPassword(); // get new password
+
+ if (nPassword == null) { // user cancelled - any of the above three fields is null
+ // do nothing
+ return;
+ }
+
+ // Is anything actually modified?
+ boolean isModified = (!serviceURL.equals(nServiceURL)
+ || !username.equals(nUsername) || !password
+ .equals(nPassword));
+
+ if (isModified) {
+ // Check if a different password entry with the new URL
+ // (i.e. alias) already exists in the Keystore
+ // We ask this here as the user may wish to overwrite that
+ // other password entry.
+
+ // Get list of URLs for all passwords in the Keystore
+ ArrayList<String> serviceURLs = null;
+ try{
+ serviceURLs = credManager.getServiceURLsforUsernameAndPasswords();
+ }
+ catch(CMException cme){
+ String exMessage = "Failed to get service URLs for all username and password pairs to check if the modified entry already exists";
+ JOptionPane.showMessageDialog(this, exMessage,
+ "Credential Manager Error",
+ JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ // If the modified service URL already exists and is not the currently selected one
+ if ( (!nServiceURL.equals(serviceURL)) && serviceURLs.contains(nServiceURL)) {
+
+ int iSelected = JOptionPane.showConfirmDialog(this,
+ "The Keystore already contains username and password pair for the entered service URL.\n"
+ + "Do you want to overwrite it?",
+ "Credential Manager Alert",
+ JOptionPane.YES_NO_OPTION);
+
+ if (iSelected == JOptionPane.YES_OPTION) {
+
+ // Overwrite that other entry entry and save the new
+ // one in its place.
+ // Also remove the current one that we are editing -
+ // as it is replacing the other entry.
+ try{
+ credManager.deleteUsernameAndPasswordForService(serviceURL);
+ credManager.saveUsernameAndPasswordForService(nUsername, nPassword, nServiceURL);
+ break;
+ }
+ catch (CMException cme){
+ String exMessage = "Failed to update the username and password pair in the Keystore";
+ JOptionPane.showMessageDialog(this, exMessage,
+ "Credential Manager Error",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ // Otherwise show the same window with the entered
+ // service URL, username and password values
+ }
+ else {
+ try{
+ if ( !nServiceURL.equals(serviceURL)) {
+ credManager.deleteUsernameAndPasswordForService(serviceURL);
+ }
+ credManager.saveUsernameAndPasswordForService(nUsername, nPassword, nServiceURL);
+ break;
+ }
+ catch (CMException cme){
+ String exMessage = "Failed to update the username and password pair in the Keystore";
+ JOptionPane.showMessageDialog(this, exMessage,
+ "Credential Manager Error",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+ else{ // nothing actually modified by OK pressed
+ break;
+ }
+ }
+ }
+
+ /**
+ * Delete the selected username and password entries from the Keystore.
+ */
+ private void deletePassword() {
+
+ // Which entries have been selected?
+ int[] iRows = passwordsTable.getSelectedRows();
+ if (iRows.length == 0) { // no password entry selected
+ return;
+ }
+
+ // Ask user to confirm the deletion
+ int iSelected = JOptionPane
+ .showConfirmDialog(
+ null,
+ "Are you sure you want to delete the selected username and password entries?",
+ "Credential Manager Alert",
+ JOptionPane.YES_NO_OPTION);
+
+ if (iSelected != JOptionPane.YES_OPTION) {
+ return;
+ }
+
+ for (int i = iRows.length - 1; i >= 0; i--) { // delete from backwards
+ // Get service URL for the current entry
+ String serviceURL = (String) passwordsTable.getValueAt(iRows[i], 1); // current entry's service URL
+ try {
+ // Delete the password entry from the Keystore
+ credManager.deleteUsernameAndPasswordForService(serviceURL);
+ }
+ catch (CMException cme) {
+ String exMessage = "Failed to delete the username and password pair from the Keystore";
+ JOptionPane.showMessageDialog(this, exMessage,
+ "Credential Manager Error",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+
+ /**
+ * Show the contents of a (user or trusted) certificate.
+ */
+ @SuppressWarnings("unchecked")
+ private void viewCertificate() {
+
+ int iRow = -1;
+ String alias = null;
+ X509Certificate certToView = null;
+ ArrayList<String> serviceURLs = null;
+ String keystoreType = null;
+
+ // Are we showing user's public key certificate?
+ if (keyPairsTab.isShowing()){
+ keystoreType = CredentialManager.KEYSTORE;
+ iRow = keyPairsTable.getSelectedRow();
+
+ if (iRow != - 1){
+ // Because the alias column is not visible we call the
+ // getValueAt method on the table model rather than at the JTable
+ alias = (String) keyPairsTable.getModel().getValueAt(iRow, 6); // current entry's Keystore alias
+
+ // Get the list of service URLs for the entry
+ serviceURLs = (ArrayList<String>) keyPairsTable.getModel().getValueAt(iRow, 5);
+ }
+ }
+ // Are we showing trusted certificate?
+ else if(trustedCertificatesTab.isShowing()){
+ keystoreType = CredentialManager.TRUSTSTORE;
+ iRow = trustedCertsTable.getSelectedRow();
+
+ if (iRow != - 1){
+
+ // Get the selected trusted certificate entry's Truststore alias
+ // Alias column is invisible so we get the value from the table model
+ alias = (String) trustedCertsTable.getModel()
+ .getValueAt(iRow, 5);
+ }
+ }
+
+ if (iRow != -1) { // something has been selected
+ try {
+ // Get the entry's certificate
+ certToView = CMX509Util.convertCertificate(credManager
+ .getCertificate(keystoreType, alias));
+
+ // Supply the certificate and list of URLs to the view
+ // certificate dialog.
+ ViewCertDetailsDialog viewCertDetailsDialog = new ViewCertDetailsDialog(
+ this, "Certificate details", true, certToView,
+ serviceURLs);
+ viewCertDetailsDialog.setLocationRelativeTo(this);
+ viewCertDetailsDialog.setVisible(true);
+ }
+ catch (CMException cme) {
+ String exMessage = "Failed to get certificate details to display to the user";
+ logger.error(exMessage);
+ JOptionPane.showMessageDialog(this, exMessage,
+ "Credential Manager Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+
+ /**
+ * Import a key pair from a PKCS #12 keystore file to the Keystore.
+ */
+ private void newKeyPair() {
+
+ // Let the user choose a PKCS #12 file (keystore) containing a public
+ // and private key pair to import
+ File importFile = selectImportExportFile(
+ "PKCS #12 file to import from", // title
+ new String[] { ".p12", ".pfx" }, // array of file extensions
+ // for the file filter
+ "PKCS#12 Files (*.p12, *.pfx)", // description of the filter
+ "Import"); // text for the file chooser's approve button
+
+ if (importFile == null) {
+ return;
+ }
+
+ // The PKCS #12 keystore is not a file
+ if (!importFile.isFile()) {
+ JOptionPane.showMessageDialog(this, "Your selection is not a file",
+ "Credential Manager Alert", JOptionPane.WARNING_MESSAGE);
+ return;
+ }
+
+ // Get the user to enter the password that was used to encrypt the
+ // private key contained in the PKCS #12 file
+ GetPasswordDialog dGetPassword = new GetPasswordDialog(this,
+ "Import key pair entry", true,
+ "Enter the password that was used to encrypt the PKCS #12 file");
+ dGetPassword.setLocationRelativeTo(this);
+ dGetPassword.setVisible(true);
+
+ String pkcs12Password = dGetPassword.getPassword();
+
+ if (pkcs12Password == null) { // user cancelled
+ return;
+ } else if (pkcs12Password.length() == 0) { // empty password
+ // FIXME: Maybe user did not have the password set for the private key???
+ return;
+ }
+
+ try {
+ // Load the PKCS #12 keystore from the file using BC provider
+ KeyStore pkcs12 = credManager.loadPKCS12Keystore(importFile, pkcs12Password);
+
+ // Display the import key pair dialog supplying all the private keys
+ // stored in the PKCS #12 file
+ // and a field for the user to enter service URL associated with the
+ // selected key pair
+ // Typically there will be only one private key inside, but could be
+ // more
+ NewKeyPairEntryDialog dImportKeyPair = new NewKeyPairEntryDialog(
+ this, "Credential Manager", true, pkcs12);
+ dImportKeyPair.setLocationRelativeTo(this);
+ dImportKeyPair.setVisible(true);
+
+ // Get the private key and certificate chain of the key pair
+ Key privateKey = dImportKeyPair.getPrivateKey();
+ Certificate[] certChain = dImportKeyPair.getCertificateChain();
+
+ // Get the service URLs
+ ArrayList<String> serviceURLs = dImportKeyPair.getServiceURLs();
+
+ if (privateKey == null || certChain == null) {
+ // User did not select a key pair for import or cancelled
+ return;
+ }
+
+ // Check if a key pair entry with the same alias already exists in
+ // the Keystore
+ if (credManager.containsKeyPair(privateKey, certChain)) {
+ int iSelected = JOptionPane
+ .showConfirmDialog(
+ this,
+ "The keystore already contains the key pair entry with the same private key.\nDo you want to overwrite it?",
+ "Credential Manager Alert",
+ JOptionPane.YES_NO_OPTION);
+
+ if (iSelected != JOptionPane.YES_OPTION) {
+ return;
+ }
+ }
+
+ // Place the private key and certificate chain into the Keystore
+ // and save the service URLs list associated with this key pair
+ credManager.saveKeyPair(privateKey, certChain, serviceURLs);
+
+ // Display success message
+ JOptionPane
+ .showMessageDialog(this, "Key pair import successful",
+ "Credential Manager Alert",
+ JOptionPane.INFORMATION_MESSAGE);
+ }
+ catch (Exception ex) { // too many exceptions to catch separately
+ String exMessage = "Failed to import the key pair entry to the Keystore. "
+ + ex.getMessage();
+ logger.error(exMessage);
+ JOptionPane.showMessageDialog(this, exMessage,
+ "Credential Manager Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+
+ /**
+ * Edit service URLs for a given key pair entry.
+ */
+ @SuppressWarnings("unchecked")
+ private void editKeyPair() {
+ // Which key pair entry has been selected?
+ int iRow = keyPairsTable.getSelectedRow();
+ if (iRow == -1) { // no row currently selected
+ return;
+ }
+
+ // Because the alias column is not visible we call the
+ // getValueAt method on the table model rather than at the JTable
+ String alias = (String) keyPairsTable.getModel().getValueAt(iRow, 6); // current entry's Keystore alias
+
+ // Get the list of URLs for the alias
+ ArrayList<String> serviceURLs = (ArrayList<String>) keyPairsTable.getModel().getValueAt(iRow, 5);
+
+ // Let the user edit the list of service urls this key pair is
+ // associated to
+ EditKeyPairEntryDialog dEditKeyPair = new EditKeyPairEntryDialog(this,
+ "Edit key pair's service URLs", true, serviceURLs);
+
+ dEditKeyPair.setLocationRelativeTo(this);
+ dEditKeyPair.setVisible(true);
+
+ ArrayList<String> newServiceURLs = dEditKeyPair.getServiceURLs(); // new service URLs list
+
+ if (newServiceURLs == null) { // user cancelled
+ return;
+ }
+
+ // Is anything actually modified?
+ boolean isModified = (!serviceURLs.equals(newServiceURLs));
+
+ if (isModified) {
+ try {
+ // Add the new list of URLs for the alias
+ credManager.saveServiceURLsForKeyPair(alias, newServiceURLs);
+ }
+ catch (CMException cme) {
+ String exMessage = "Failed to update service URLs for the key pair entry";
+ logger.error(exMessage);
+ JOptionPane.showMessageDialog(this, exMessage,
+ "Credential Manager Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+
+ /**
+ * Export user's private and public key pair to a PKCS #12
+ * keystore file.
+ */
+ private void exportKeyPair() {
+
+ // Which key pair entry has been selected?
+ int iRow = keyPairsTable.getSelectedRow();
+ if (iRow == -1) { // no row currently selected
+ return;
+ }
+
+ // Get the key pair entry's Keystore alias
+ String alias = (String) keyPairsTable.getModel().getValueAt(iRow, 6);
+
+ // Let the user choose a PKCS #12 file (keystore) to export public and
+ // private key pair to
+ File exportFile = selectImportExportFile("Select a file to export to", // title
+ new String[] { ".p12", ".pfx" }, // array of file extensions
+ // for the file filter
+ "PKCS#12 Files (*.p12, *.pfx)", // description of the filter
+ "Export"); // text for the file chooser's approve button
+
+ if (exportFile == null) {
+ return;
+ }
+
+ // If file already exist - ask the user if he wants to overwrite it
+ if (exportFile.isFile()) {
+ int iSelected = JOptionPane
+ .showConfirmDialog(
+ this,
+ "The file with the given name already exists.\nDo you want to overwrite it?",
+ "Credential Manager Alert",
+ JOptionPane.YES_NO_OPTION);
+
+ if (iSelected == JOptionPane.NO_OPTION) {
+ return;
+ }
+ }
+
+ // Get the user to enter the password for the PKCS #12 keystore file
+ GetPasswordDialog dGetPassword = new GetPasswordDialog(this,
+ "Credential Manager", true,
+ "Enter the password for protecting the exported key pair");
+ dGetPassword.setLocationRelativeTo(this);
+ dGetPassword.setVisible(true);
+
+ String pkcs12Password = dGetPassword.getPassword();
+
+ if (pkcs12Password == null) { // user cancelled or empty password
+ // Warn the user
+ JOptionPane
+ .showMessageDialog(
+ this,
+ "You must supply a password for protecting the exported key pair.",
+ "Credential Manager Alert",
+ JOptionPane.INFORMATION_MESSAGE);
+ return;
+ }
+
+ // Export the key pair
+ try {
+ credManager.exportKeyPair(alias, exportFile, pkcs12Password);
+ JOptionPane.showMessageDialog(this, "Key pair export successful",
+ "Credential Manager Alert",
+ JOptionPane.INFORMATION_MESSAGE);
+ }
+ catch (CMException cme) {
+ JOptionPane.showMessageDialog(this, cme.getMessage(),
+ "Credential Manager Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+ /**
+ * Delete selected key pair entries from the Keystore.
+ */
+ private void deleteKeyPair() {
+
+ // Which entries have been selected?
+ int[] iRows = keyPairsTable.getSelectedRows();
+ if (iRows.length == 0) { // no key pair entry selected
+ return;
+ }
+
+ // Ask user to confirm the deletion
+ int iSelected = JOptionPane
+ .showConfirmDialog(
+ null,
+ "Are you sure you want to delete the selected key pairs?",
+ "Credential Manager Alert",
+ JOptionPane.YES_NO_OPTION);
+
+ if (iSelected != JOptionPane.YES_OPTION) {
+ return;
+ }
+
+ for (int i = iRows.length - 1; i >= 0; i--) { // delete from backwards
+ // Get the alias for the current entry
+ String alias = (String) keyPairsTable.getModel().getValueAt(
+ iRows[i], 6);
+ try {
+ // Delete the key pair entry from the Keystore
+ // and URLs associated with this key pair entry
+ credManager.deleteKeyPair(alias);
+ }
+ catch (CMException cme) {
+ String exMessage = "Failed to delete the key pair(s) from the Keystore";
+ JOptionPane.showMessageDialog(this, exMessage,
+ "Credential Manager Error",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+
+ /**
+ * Show the contents of a proxy certificate.
+ */
+ private void viewProxyCertificate() {
+
+ int iRow = proxiesTable.getSelectedRow();
+
+ if (iRow != -1) { // something has been selected
+ String alias = (String) proxiesTable.getModel().getValueAt(iRow, 5);
+
+ if (alias.startsWith("cagridproxy#")){ // cagrid proxy
+ try {
+ // Get the entry's certificate
+ X509Certificate certToView = CMX509Util.convertCertificate(credManager
+ .getCertificate(CredentialManager.KEYSTORE, alias));
+
+ String authNServiceURL = alias.substring(alias.indexOf('#') + 1, alias.indexOf(' '));
+ String dorianServiceURL = alias.substring(alias.indexOf(' ') +1);
+ // Supply the certificate and list of URLs to the view
+ // certificate dialog.
+ ViewCaGridProxyCertDetailsDialog viewCaGridProxyCertDetailsDialog = new ViewCaGridProxyCertDetailsDialog(
+ this, "Certificate details", true, certToView, authNServiceURL, dorianServiceURL);
+ viewCaGridProxyCertDetailsDialog.setLocationRelativeTo(this);
+ viewCaGridProxyCertDetailsDialog.setVisible(true);
+ }
+ catch (CMException cme) {
+ String exMessage = "Failed to get proxy certificate details to display to the user";
+ logger.error(exMessage);
+ JOptionPane.showMessageDialog(this, exMessage,
+ "Credential Manager Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ //else{} // some other proxy
+ }
+ }
+
+ /**
+ * Delete selected proxy entries from the Keystore.
+ */
+ private void deleteProxy() {
+
+ // Which entries have been selected?
+ int[] iRows = proxiesTable.getSelectedRows();
+ if (iRows.length == 0) { // no key pair entry selected
+ return;
+ }
+
+ // Ask user to confirm the deletion
+ int iSelected = JOptionPane
+ .showConfirmDialog(
+ null,
+ "Are you sure you want to delete the selected proxy(ies)?",
+ "Credential Manager Alert",
+ JOptionPane.YES_NO_OPTION);
+
+ if (iSelected != JOptionPane.YES_OPTION) {
+ return;
+ }
+
+ for (int i = iRows.length - 1; i >= 0; i--) { // delete from backwards
+ // Get the alias for the current entry
+ String alias = (String) proxiesTable.getModel().getValueAt(
+ iRows[i], 5);
+ try {
+ // Delete the proxy entry from the Keystore
+ credManager.deleteCaGridProxy(alias);
+ }
+ catch (CMException cme) {
+ String exMessage = "Failed to delete the proxy(ies) from the Keystore";
+ logger.error(exMessage);
+ JOptionPane.showMessageDialog(this, exMessage,
+ "Credential Manager Error",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+
+ /**
+ * Import a trusted certificate from a PEM or DER encoded file
+ * into the Truststore.
+ */
+ private void importTrustedCertificate() {
+ // Let the user choose a file containing trusted certificate(s) to
+ // import
+ File certFile = selectImportExportFile(
+ "Certificate file to import from", // title
+ new String[] { ".pem", "crt", ".cer", ".der", ".p7c" }, // file extensions filters
+ "Certificate Files (*.pem, *.crt, , *.cer, *.der, *.p7c)", // filter description
+ "Import"); // text for the file chooser's approve button
+
+ if (certFile == null) {
+ return;
+ }
+
+ // Load the certificate(s) from the file
+ ArrayList<X509Certificate> trustCertsList = new ArrayList<X509Certificate>();
+ FileInputStream fis = null;
+
+ try {
+ fis = new FileInputStream(certFile);
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ // The following should be able to load PKCS #7 certificate chain files
+ // as well as ASN.1 DER or PEM-encoded (sequences of) certificates
+ Collection<? extends Certificate> c = cf.generateCertificates(fis);
+ Iterator<? extends Certificate> i = c.iterator();
+ while (i.hasNext()) {
+ trustCertsList.add((X509Certificate) i.next());
+ }
+ }
+ catch (Exception cex) {
+ // Do nothing
+ }
+ finally {
+ try {
+ fis.close();
+ } catch (Exception ex) {
+ // ignore
+ }
+ }
+
+ if (trustCertsList.size() == 0) { // Could not load certificates as
+ // any of the above types
+ try {
+ // Try as openssl PEM format - which sligtly differs from the
+ // one supported by JCE
+ fis = new FileInputStream(certFile);
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ PEMReader pr = new PEMReader(new InputStreamReader(fis), null,
+ cf.getProvider().getName());
+ Object cert;
+ while ((cert = pr.readObject()) != null) {
+ if (cert instanceof X509Certificate) {
+ trustCertsList.add((X509Certificate) cert);
+ }
+ }
+ } catch (Exception cex) {
+ // do nothing
+ } finally {
+ try {
+ fis.close();
+ } catch (Exception ex) {
+ // ignore
+ }
+ }
+ }
+
+ if (trustCertsList.size() == 0) { // Failed to load certifcate(s)
+ // using any of the known encodings
+ JOptionPane
+ .showMessageDialog(
+ this,
+ "Failed to load certificate(s) using any of the known encodings -\nfile format not recognised.",
+ "Credential Manager Error",
+ JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ // Show the list of certificates contained in the file for the user to
+ // select the ones to import
+ NewTrustCertsDialog dImportTrustCerts = new NewTrustCertsDialog(this,
+ "Credential Manager", true, trustCertsList);
+
+ dImportTrustCerts.setLocationRelativeTo(this);
+ dImportTrustCerts.setVisible(true);
+ ArrayList<X509Certificate> selectedTrustCerts = dImportTrustCerts
+ .getTrustedCertificates(); // user-selected trusted certs to import
+
+ // If user cancelled or did not select any cert to import
+ if ((selectedTrustCerts) == null || (selectedTrustCerts.size() == 0)) {
+ return ;
+ }
+
+ try {
+
+ for (int i = selectedTrustCerts.size() - 1; i >= 0; i--) {
+ // Import the selected trusted certificates
+ credManager.saveTrustedCertificate(selectedTrustCerts.get(i));
+ }
+
+ // Display success message
+ JOptionPane
+ .showMessageDialog(this,
+ "Trusted certificate(s) import successful",
+ "Credential Manager Alert",
+ JOptionPane.INFORMATION_MESSAGE);
+ }
+ catch (CMException cme) {
+ String exMessage = "Failed to import trusted certificate(s) to the Truststore";
+ logger.error(exMessage);
+ JOptionPane.showMessageDialog(this, exMessage,
+ "Credential Manager Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+
+
+ /**
+ * Lets the user export one (at the moment) or more (in future) trusted
+ * certificate entries to a PEM-encoded file.
+ *
+ * @return True if the export is successful, false otherwise
+ */
+ private boolean exportTrustedCertificate() {
+
+ // Which trusted certificate has been selected?
+ int iRow = trustedCertsTable.getSelectedRow();
+ if (iRow == -1) { // no row currently selected
+ return false;
+ }
+
+ // Get the trust certificate entry's Keystore alias
+ String alias = (String) trustedCertsTable.getModel().getValueAt(iRow, 3);
+ // the alias column is invisible so we get the value from the table model
+
+ // Let the user choose a file to export public and private key pair to
+ File exportFile = selectImportExportFile("Select a file to export to", // title
+ new String[] { ".pem" }, // array of file extensions for the
+ // file filter
+ "Certificate Files (*.pem)", // description of the filter
+ "Export"); // text for the file chooser's approve button
+
+ if (exportFile == null) {
+ return false;
+ }
+
+ // If file already exist - ask the user if he wants to overwrite it
+ if (exportFile.isFile()) {
+ int iSelected = JOptionPane
+ .showConfirmDialog(
+ this,
+ "The file with the given name already exists.\nDo you want to overwrite it?",
+ "Credential Manager Alert",
+ JOptionPane.YES_NO_OPTION);
+
+ if (iSelected == JOptionPane.NO_OPTION) {
+ return false;
+ }
+ }
+
+ // Export the trusted certificate
+ PEMWriter pw = null;
+ try {
+ // Get the trusted certificate
+ Certificate certToExport = credManager.getCertificate(
+ CredentialManager.TRUSTSTORE, alias);
+ pw = new PEMWriter(new FileWriter(exportFile));
+ pw.writeObject(certToExport);
+
+ JOptionPane
+ .showMessageDialog(this,
+ "Trusted certificate export successful",
+ "Credential Manager Alert",
+ JOptionPane.INFORMATION_MESSAGE);
+
+ return true;
+ }
+ catch (Exception ex) {
+ String exMessage = "Failed to export the trusted certificate from the Truststore.";
+ logger.error(exMessage);
+ JOptionPane.showMessageDialog(
+ this,
+ exMessage,
+ "Credential Manager Error",
+ JOptionPane.ERROR_MESSAGE);
+ return false;
+ }
+ finally {
+ if (pw != null) {
+ try {
+ pw.close();
+ } catch (IOException ex) {
+ // ignore
+ }
+ }
+ }
+ }
+
+ /**
+ * Delete selected trusted certificate entries from the Truststore.
+ */
+ private void deleteTrustedCertificate() {
+
+ // Which entries have been selected?
+ int[] iRows = trustedCertsTable.getSelectedRows();
+ if (iRows.length == 0) { // no trusted cert entry selected
+ return;
+ }
+
+ // Ask user to confirm the deletion
+ int iSelected = JOptionPane
+ .showConfirmDialog(
+ null,
+ "Are you sure you want to delete the selected trusted certificate(s)?",
+ "Credential Manager Alert",
+ JOptionPane.YES_NO_OPTION);
+
+ if (iSelected != JOptionPane.YES_OPTION) {
+ return;
+ }
+
+ for (int i = iRows.length - 1; i >= 0; i--) { // delete from backwards
+ // Get the alias for the current entry
+ String alias = (String) trustedCertsTable.getModel().getValueAt(
+ iRows[i], 5);
+ try {
+ // Delete the trusted certificate entry from the Truststore
+ credManager.deleteTrustedCertificate(alias);
+ }
+ catch (CMException cme) {
+ String exMessage = "Failed to delete the trusted certificate(s) from the Truststore";
+ logger.error(exMessage);
+ JOptionPane.showMessageDialog(this, exMessage,
+ "Credential Manager Error",
+ JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+
+ /**
+ * Handle double click on the Keystore tables. If it has occurred, show the
+ * details of the entry clicked upon.
+ */
+ private void tableDoubleClick(MouseEvent evt) {
+ if (evt.getClickCount() > 1) { // is it double click?
+
+ // What row and column were clicked upon (if any)?
+ Point point = new Point(evt.getX(), evt.getY());
+ int iRow = ((JTable) evt.getSource()).rowAtPoint(point);
+ if (iRow == -1) {
+ return;
+ }
+ // Which table the click occured on?
+ if (((JTable) evt.getSource()).getModel() instanceof PasswordsTableModel) { // Passwords table
+ viewPassword();
+ }
+ else if (((JTable) evt.getSource()).getModel() instanceof KeyPairsTableModel) { // Key pairs table
+ viewCertificate();
+ }
+ else if (((JTable) evt.getSource()).getModel() instanceof ProxiesTableModel) { //Proxies table
+ viewProxyCertificate();
+ }
+ else { // Trusted certificates table
+ viewCertificate();
+ }
+ }
+ }
+
+ /**
+ * Let the user select a file to export to or import from a key pair or a
+ * certificate. The file types are filtered according to their extensions:
+ * .p12 or .pfx are PKCS #12 keystore files containing private key and its
+ * public key (+cert chain) .crt 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
+ */
+ private File selectImportExportFile(String title, String[] filter,
+ String description, String approveButtonText) {
+
+ JFileChooser chooser = new JFileChooser();
+ chooser
+ .addChoosableFileFilter(new CryptoFileFilter(filter,
+ description));
+ chooser.setDialogTitle(title);
+ chooser.setMultiSelectionEnabled(false);
+
+ int rtnValue = chooser.showDialog(this, approveButtonText);
+ if (rtnValue == JFileChooser.APPROVE_OPTION) {
+ File selectedFile = chooser.getSelectedFile();
+ return selectedFile;
+ }
+ return null;
+ }
+
+ /**
+ * Exit the UI's frame.
+ */
+ private void closeFrame() {
+ setVisible(false);
+ dispose();
+ }
+
+
+// /**
+// * Set cursor to busy and disable application input. This can be reversed by
+// * a subsequent call to setCursorFree.
+// */
+// private void setCursorBusy() {
+// // Block all mouse events using glass pane
+// Component glassPane = getRootPane().getGlassPane();
+// glassPane.addMouseListener(new MouseAdapter() {
+// });
+// glassPane.setVisible(true);
+//
+// // Set cursor to busy
+// glassPane.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
+// }
+//
+//
+// /**
+// * Set cursor to free and enable application input. Called after a call to
+// * setCursorBusy.
+// */
+// private void setCursorFree() {
+// // Accept mouse events
+// Component glassPane = getRootPane().getGlassPane();
+// glassPane.setVisible(false);
+//
+// // Revert cursor to default
+// glassPane.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+// }
+//
+// /**
+// * Action helper class.
+// */
+// private abstract class AbstractAction extends javax.swing.AbstractAction {
+// protected abstract void act();
+//
+// public void actionPerformed(ActionEvent evt) {
+// setCursorBusy();
+// repaint();
+// new Thread(new Runnable() {
+// public void run() {
+// try {
+// act();
+// } finally {
+// setCursorFree();
+// }
+// }
+// }).start();
+// }
+// }
+
+}
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/CredentialManagerUILauncher.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/CredentialManagerUILauncher.java
new file mode 100644
index 0000000..cc7500a
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/CredentialManagerUILauncher.java
@@ -0,0 +1,117 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager;
+
+import java.awt.BorderLayout;
+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;
+import javax.swing.SwingUtilities;
+import javax.swing.WindowConstants;
+
+/**
+ *
+ * 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(){
+
+ public void actionPerformed(ActionEvent e) {
+ CredentialManagerUI cmGUI = CredentialManagerUI.getInstance();
+ //if (cmGUI.isInitialised()){
+ cmGUI.setVisible(true);
+ //}
+ }
+ });
+
+ jpLaunch.add(jlLaunch);
+ jpLaunch.add(jbLaunch);
+
+ getContentPane().add(jpLaunch,BorderLayout.CENTER);
+
+ // Handle application close
+ setDefaultCloseOperation(WindowConstants.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);
+
+ }
+
+
+ /**
+ * Runnable to create and show the Credential Manager Launcher's GUI.
+ */
+ private static class CreateAndShowGui
+ implements Runnable
+ {
+
+ /**
+ * Create and show the launcher GUI.
+ */
+ public void run()
+ {
+ new CredentialManagerUILauncher();
+ }
+ }
+
+
+ /**
+ * Launcher for the Credential Manager GUI.
+ */
+ public static void main(String[] args)
+ {
+ // Create and show GUI on the event handler thread
+ SwingUtilities.invokeLater(new CreateAndShowGui());
+ }
+
+}
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/CryptoFileFilter.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/CryptoFileFilter.java
new file mode 100644
index 0000000..4b49868
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/CryptoFileFilter.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * File filter for filtering against various file extensions.
+ *
+ * @author Alexandra Nenadic
+ */
+public class CryptoFileFilter extends javax.swing.filechooser.FileFilter
+{
+ /** Description of the filter */
+ private String description;
+
+ /** Array of file extensions to filter against */
+ private ArrayList<String> exts = new ArrayList<String>();
+
+ /**
+ * Construct a CryptoFileFilter for a set of related file extensions.
+ *
+ * @param extList Array of file extensions
+ * @param sDescription Short collective description for the file extensions
+ */
+ public CryptoFileFilter(String [] extList, String sDescription)
+ {
+ for (int i = 0; i < extList.length; i++) {
+ addType (extList[i]);
+ }
+ description = sDescription;
+ }
+
+ private void addType(String s) {
+ exts.add(s);
+ }
+
+ /** Return true if the given file is accepted by this filter. */
+ public boolean accept(File f)
+ {
+ // Little trick: if you don't do this, only directory names
+ // ending in one of the extentions appear in the window.
+ if (f.isDirectory())
+ {
+ return true;
+ }
+ else if (f.isFile())
+ {
+ Iterator<String> it = exts.iterator();
+ while (it.hasNext()) {
+ if (f.getName().toLowerCase().endsWith((String) it.next()))
+ return true;
+ }
+ }
+ // A file that didn't match.
+ return false;
+ }
+
+ /** Set the printable description of this filter. */
+ public void setDescription(String s) {
+ description = s;
+ }
+
+ /** Return the printable description of this filter. */
+ public String getDescription() {
+ return description;
+ }
+ }
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/EditKeyPairEntryDialog.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/EditKeyPairEntryDialog.java
new file mode 100644
index 0000000..3f72a34
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/EditKeyPairEntryDialog.java
@@ -0,0 +1,360 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager;
+
+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.DefaultListModel;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JOptionPane;
+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.log4j.Logger;
+
+import net.sf.taverna.t2.security.credentialmanager.CMException;
+import net.sf.taverna.t2.security.credentialmanager.CredentialManager;
+import net.sf.taverna.t2.workbench.ui.credentialmanager.GetServiceURLDialog;
+
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Set;
+import java.awt.Dimension;
+
+/**
+ * Dialog used for editing service urls associated with a key pair entry.
+ *
+ * @author Alex Nenadic
+ */
+@SuppressWarnings("serial")
+public class EditKeyPairEntryDialog
+ extends JDialog
+{
+
+ // Service URLs entry list
+ private JList jltServiceURLs;
+
+ // Stores service URLs entered
+ private ArrayList<String> serviceURLs;
+
+ private Logger logger = Logger.getLogger(EditKeyPairEntryDialog.class);
+
+ /**
+ * Creates new EditKeyPairEntryDialog dialog where the parent is a frame.
+ */
+ public EditKeyPairEntryDialog(JFrame parent, String title, boolean modal, ArrayList<String> serviceURLs)
+ {
+ super(parent, title, modal);
+ this.serviceURLs = serviceURLs;
+ initComponents();
+ }
+
+ /**
+ * Creates new EditKeyPairEntryDialog dialog where the parent is a dialog.
+ */
+ public EditKeyPairEntryDialog(JDialog parent, String title, boolean modal, ArrayList<String> serviceURLs)
+ {
+ super(parent, title, modal);
+ this.serviceURLs = serviceURLs;
+ initComponents();
+ }
+
+ /**
+ * Get the service URLs set in the dialog.
+ */
+ public ArrayList<String> getServiceURLs()
+ {
+ return serviceURLs;
+ }
+
+ /**
+ * Initialise the dialog's GUI components.
+ */
+ private void initComponents()
+ {
+ getContentPane().setLayout(new BorderLayout());
+
+ // Label
+ JLabel jlServiceURLs = new JLabel("Service URLs this key pair will be used for:");
+ jlServiceURLs.setFont(new Font(null, Font.PLAIN, 11));
+ jlServiceURLs.setBorder(new EmptyBorder(5,5,5,5));
+
+ // Service URLs list
+ DefaultListModel jltModel = new DefaultListModel();
+ jltServiceURLs = new JList(jltModel);
+ // Populate the list with current values
+ for (String url : serviceURLs){
+ jltModel.addElement(url);
+ }
+ jltServiceURLs.setVisibleRowCount(5); //don't show more than 5, otherwise the window is too big
+
+ // 'Add' service URL button
+ JButton addButton = new JButton("+");
+ addButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent evt)
+ {
+ addServiceURLPressed();
+ }
+ });
+ addButton.setEnabled(true);
+ // 'Remove' service URL button
+ final JButton removeButton = new JButton("-");
+ removeButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent evt)
+ {
+ // get selected indices
+ int[] selected = jltServiceURLs.getSelectedIndices();
+ for (int i = selected.length -1; i>=0 ; i--){
+ ((DefaultListModel) jltServiceURLs.getModel()).remove(selected[i]);
+ }
+ }
+ });
+ removeButton.setEnabled(false);
+ jltServiceURLs.addListSelectionListener(new ListSelectionListener()
+ {
+ public void valueChanged(ListSelectionEvent evt)
+ {
+ if (jltServiceURLs.getSelectedIndex() == -1) {
+ removeButton.setEnabled(false);
+ }
+ else {
+ removeButton.setEnabled(true);
+ }
+ }
+ });
+
+ // Scroll pane for service URLs list
+ JScrollPane jspServiceURLs = new JScrollPane(jltServiceURLs,
+ JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ jspServiceURLs.getViewport().setBackground(jltServiceURLs.getBackground());
+
+ // Panel for Add and Remove buttons
+ JPanel jpServiceURLsButtons = new JPanel(new FlowLayout(FlowLayout.CENTER));
+ jpServiceURLsButtons.add(addButton);
+ jpServiceURLsButtons.add(removeButton);
+
+ // Panel to hold the list scroll pane and Add/Remove buttons panel
+ JPanel jpServiceURLs = new JPanel(new BorderLayout());
+ jpServiceURLs.add(jlServiceURLs, BorderLayout.NORTH);
+ jpServiceURLs.add(jspServiceURLs, BorderLayout.CENTER);
+ jpServiceURLs.add(jpServiceURLsButtons, BorderLayout.SOUTH);
+ jpServiceURLs.setBorder(new CompoundBorder(
+ new EmptyBorder(15, 15, 15, 15), new EtchedBorder()));
+ jpServiceURLs.setPreferredSize(new Dimension(300, 250));
+
+ // OK button
+ JButton jbOK = new JButton("OK");
+ jbOK.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent evt)
+ {
+ okPressed();
+ }
+ });
+
+ // Cancel buton
+ JButton jbCancel = new JButton("Cancel");
+ jbCancel.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent evt)
+ {
+ cancelPressed();
+ }
+ });
+
+ // Panel for OK and Cancel buttons
+ JPanel jpButtons = new JPanel(new FlowLayout(FlowLayout.CENTER));
+ jpButtons.add(jbOK);
+ jpButtons.add(jbCancel);
+
+ getContentPane().add(jpServiceURLs, BorderLayout.CENTER);
+ getContentPane().add(jpButtons, BorderLayout.SOUTH);
+
+ addWindowListener(new WindowAdapter()
+ {
+ public void windowClosing(WindowEvent evt)
+ {
+ closeDialog();
+ }
+ });
+
+ setResizable(false);
+
+ getRootPane().setDefaultButton(jbOK);
+
+ pack();
+ }
+
+ /**
+ * OK button pressed or otherwise activated.
+ */
+ private void okPressed()
+ {
+ // Get Service URLs
+ serviceURLs = new ArrayList<String>();
+ Enumeration<?> URLs = (((DefaultListModel) jltServiceURLs.getModel()).elements());
+ for( ; URLs.hasMoreElements(); ){
+ serviceURLs.add((String) URLs.nextElement());
+ }
+ closeDialog();
+ }
+
+
+ /**
+ * Add Service URL button pressed.
+ */
+ public void addServiceURLPressed(){
+
+ // Display the dialog for entering service URL
+ GetServiceURLDialog dGetServiceURL = new GetServiceURLDialog(this, true);
+
+ dGetServiceURL.setLocationRelativeTo(this);
+ dGetServiceURL.setVisible(true);
+
+ String sURL = dGetServiceURL.getServiceURL();
+
+ if (sURL == null){ // user cancelled
+ return;
+ }
+
+ if (sURL.length() == 0){ // user entered empty URL
+ // Warn the user
+ JOptionPane.showMessageDialog(
+ this,
+ "The URL cannot be empty",
+ "Credential Manager Alert",
+ JOptionPane.INFORMATION_MESSAGE);
+ return;
+ }
+
+ // Check if the entered URL already exist in the URL list for this key entry
+ if (((DefaultListModel) jltServiceURLs.getModel()).contains(sURL)){
+
+ // Warn the user
+ JOptionPane.showMessageDialog(
+ this,
+ "The entered URL already exists in the list of URLs for this key pair entry",
+ "Credential Manager Alert",
+ JOptionPane.INFORMATION_MESSAGE);
+ return;
+ }
+
+ // Check if the entered URL is already associated with another key pair entry in the Keystore
+ // This check should exclude the current entry from the map of URLs being searched
+ // really (we've already checked for it in the jltServiceURLs) - but does not really matter anyway
+
+ CredentialManager credManager = null;
+ try {
+ credManager = CredentialManager.getInstance();
+ } catch (CMException cme) {
+ // Failed to instantiate Credential Manager - warn the user and exit
+ String exMessage = "Failed to instantiate Credential Manager";
+ logger .error(exMessage, cme);
+ cme.printStackTrace();
+ JOptionPane.showMessageDialog(new JFrame(), exMessage,
+ "Credential Manager Error", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ HashMap<String, ArrayList<String>> urlMap = credManager.getServiceURLsforKeyPairs();
+ if (urlMap != null){ // should not be null really (although can be empty). Check anyway.
+ Set<String> aliases = urlMap.keySet();
+ for (Iterator<String> i = aliases.iterator(); i.hasNext(); ){
+ String alias = (String) i.next();
+ // Check if url list for this alias contains the newly entered url
+ ArrayList<String> urls = (ArrayList<String>) urlMap.get(alias);
+ if (urls.contains(sURL)){
+ // Warn the user and exit
+ JOptionPane.showMessageDialog(
+ this,
+ "The entered URL is already associated with another key pair entry",
+ "Credential Manager Alert",
+ JOptionPane.INFORMATION_MESSAGE);
+ return;
+ }
+ }
+ }
+
+ // Check if the entered URL is already associated with a password entry in the Keystore
+// ArrayList<String> urlList = (ArrayList<String>) ((CredentialManagerUI) this.getParent()).getURLsForPasswords();
+// // Check if this url list contains the newly entered url
+// if (urlList.contains(sURL)){
+// // Warn the user and exit
+// JOptionPane.showMessageDialog(
+// this,
+// "The entered URL is already associated with another password entry",
+// "Credential Manager Alert",
+// JOptionPane.INFORMATION_MESSAGE);
+// return;
+// }
+
+ // Otherwise - the entered URL is not already associated with a different entry in the Keystore,
+ // so add this URL to the list of URLs for this key pair entry
+ ((DefaultListModel) jltServiceURLs.getModel()).addElement(sURL);
+ int index = ((DefaultListModel) jltServiceURLs.getModel()).getSize() - 1;
+ // Element is appended to the list - get its index
+ jltServiceURLs.setSelectedIndex(index);
+ // Insure the newly added URL is visible
+ jltServiceURLs.ensureIndexIsVisible(index);
+
+ }
+
+
+ /**
+ * Cancel button pressed or otherwise activated.
+ */
+ private void cancelPressed()
+ {
+ // Set serviceURLs to null as it might have changed in the meantime
+ // if user entered some value than pressed cancel later on
+ serviceURLs = null;
+ closeDialog();
+ }
+
+ /**
+ * Close the dialog.
+ */
+ private void closeDialog()
+ {
+ setVisible(false);
+ dispose();
+ }
+}
+
+
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/GetNewPasswordDialog.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/GetNewPasswordDialog.java
new file mode 100644
index 0000000..7b8f63c
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/GetNewPasswordDialog.java
@@ -0,0 +1,228 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager;
+
+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.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+import javax.swing.border.EmptyBorder;
+
+/**
+ * Dialog used for entering and confirming a password.
+ *
+ * @author Alex Nenadic
+ */
+@SuppressWarnings("serial")
+public class GetNewPasswordDialog extends JDialog {
+
+ // Instructions for user explaining the purpose of the password
+ private String instructions = null;
+
+ // First password entry password field
+ private JPasswordField jpfFirst;
+
+ // Password confirmation entry password field
+ private JPasswordField jpfConfirm;
+
+ // Stores new password entered
+ private String password = null;
+
+ /**
+ * Creates new GetNewPasswordDialog where the parent is a frame.
+ */
+ public GetNewPasswordDialog(JFrame parent, String title, boolean modal, String instr)
+ {
+ super(parent, title, modal);
+ instructions = instr;
+ initComponents();
+ }
+
+ /**
+ * Creates new GetNewPasswordDialog where the parent is a dialog.
+ */
+ public GetNewPasswordDialog(JDialog parent, String title, boolean modal, String instr)
+ {
+ super(parent, title, modal);
+ instructions = instr;
+ initComponents();
+ }
+
+ /**
+ * Initialise the dialog's GUI components.
+ */
+ private void initComponents()
+ {
+ getContentPane().setLayout(new BorderLayout());
+
+ JLabel jlFirst = new JLabel("Enter New Password:");
+ JLabel jlConfirm = new JLabel("Confirm New Password:");
+ jpfFirst = new JPasswordField(15);
+ jpfConfirm = new JPasswordField(15);
+
+ JButton jbOK = new JButton("OK");
+ jbOK.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent evt)
+ {
+ okPressed();
+ }
+ });
+
+ JButton jbCancel = new JButton("Cancel");
+ jbCancel.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent evt)
+ {
+ cancelPressed();
+ }
+ });
+
+ JLabel jlInstructions;
+ if (instructions != null){
+ jlInstructions = new JLabel (instructions);
+ jlInstructions.setFont(new Font(null, Font.PLAIN, 11));
+ jlInstructions.setBorder(new EmptyBorder(5,5,5,5));
+ getContentPane().add(jlInstructions, BorderLayout.NORTH);
+ }
+
+ JPanel jpPassword = new JPanel(new GridLayout(2, 2, 5, 5));
+ jpPassword.add(jlFirst);
+ jpPassword.add(jpfFirst);
+ jpPassword.add(jlConfirm);
+ jpPassword.add(jpfConfirm);
+ jpPassword.setBorder(new EmptyBorder(5, 5, 5, 5));
+
+ JPanel jpButtons = new JPanel(new FlowLayout(FlowLayout.CENTER));
+ jpButtons.add(jbCancel);
+ jpButtons.add(jbOK);
+
+ getContentPane().add(jpPassword, BorderLayout.CENTER);
+ getContentPane().add(jpButtons, BorderLayout.SOUTH);
+
+ addWindowListener(new WindowAdapter()
+ {
+ public void windowClosing(WindowEvent evt)
+ {
+ closeDialog();
+ }
+ });
+
+ setResizable(false);
+
+ getRootPane().setDefaultButton(jbOK);
+
+ pack();
+ }
+
+
+ /**
+ * Get the password set in the dialog or null if none was set.
+ */
+ public String getPassword()
+ {
+ return password;
+ }
+
+ /**
+ * Check the following:
+ * <ul>
+ * <li>that the user has supplied and confirmed a password
+ * <li>that the password's match
+ * <li>that the passwords are not empty
+ * </ul>
+ * and store the new password.
+ *
+ * @return true, if the user's dialog entry matches the above criteria,
+ * false otherwise
+ */
+ private boolean checkPassword()
+ {
+ String sFirstPassword = new String(jpfFirst.getPassword());
+ String sConfirmPassword = new String(jpfConfirm.getPassword());
+
+ if ((sFirstPassword.equals(sConfirmPassword)) && (sFirstPassword.length()!= 0)) { //passwords match and not empty
+ password = sFirstPassword;
+ return true;
+ }
+ else if ((sFirstPassword.equals(sConfirmPassword)) && (sFirstPassword.length() == 0)) { //passwords match but are empty
+ JOptionPane.showMessageDialog(this,
+ "The password cannot be empty",
+ "Credential Manager Warning",
+ JOptionPane.WARNING_MESSAGE);
+
+ return false;
+ }
+ else{ // passwords do not match
+
+ JOptionPane.showMessageDialog(this,
+ "The passwords do not match",
+ "Credential Manager Warning",
+ JOptionPane.WARNING_MESSAGE);
+
+ return false;
+ }
+ }
+
+ /**
+ * OK button pressed or otherwise activated.
+ */
+ private void okPressed()
+ {
+ if (checkPassword()) {
+ closeDialog();
+ }
+ }
+
+ /**
+ * Cancel button pressed or otherwise activated.
+ */
+ private void cancelPressed()
+ {
+ // Set the password to null as it might have changed in the meantime
+ // if user entered something previously
+ password = null;
+ closeDialog();
+ }
+
+ /**
+ * Close the dialog.
+ */
+ private void closeDialog()
+ {
+ setVisible(false);
+ dispose();
+ }
+}
+
+
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/GetPasswordDialog.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/GetPasswordDialog.java
new file mode 100644
index 0000000..8f2588d
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/GetPasswordDialog.java
@@ -0,0 +1,201 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager;
+
+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.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JPasswordField;
+import javax.swing.border.EmptyBorder;
+
+/**
+ * Dialog used for entering a password.
+ *
+ * @author Alex Nenadic
+ */
+@SuppressWarnings("serial")
+public class GetPasswordDialog extends JDialog {
+
+ // Instructions for user explaining the purpose of the password
+ private String instructions = null;
+
+ // Password entry password field
+ private JPasswordField jpfPassword;
+
+ // Stores the password entered
+ private String password = null;
+
+ /**
+ * Creates new GetPasswordDialog dialog where the parent is a frame.
+ */
+ public GetPasswordDialog(JFrame parent, String title, boolean modal, String instr)
+ {
+ super(parent, title, modal);
+ instructions = instr;
+ initComponents();
+ }
+
+ /**
+ * Creates new GetPasswordDialog dialog where the parent is a dialog.
+ */
+ public GetPasswordDialog(JDialog parent, String title, boolean modal, String instr)
+ {
+ super(parent, title, modal);
+ instructions = instr;
+ initComponents();
+ }
+
+ /**
+ * Get the password set in the dialog.
+ *
+ * @return The password or null if none was set
+ */
+ public String getPassword()
+ {
+ return password;
+ }
+
+ /**
+ * Initialise the dialog's GUI components.
+ */
+ private void initComponents()
+ {
+ getContentPane().setLayout(new BorderLayout());
+
+ JLabel jlPassword = new JLabel("Password");
+ jpfPassword = new JPasswordField(15);
+
+ JButton jbOK = new JButton("OK");
+ jbOK.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent evt)
+ {
+ okPressed();
+ }
+ });
+
+ JButton jbCancel = new JButton("Cancel");
+ jbCancel.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent evt)
+ {
+ cancelPressed();
+ }
+ });
+
+
+ JLabel jlInstructions; // Instructions
+ if (instructions != null){
+ jlInstructions = new JLabel (instructions);
+ jlInstructions.setFont(new Font(null, Font.PLAIN, 11));
+ jlInstructions.setBorder(new EmptyBorder(5,5,5,5));
+ getContentPane().add(jlInstructions, BorderLayout.NORTH);
+ }
+
+ JPanel jpPassword = new JPanel(new FlowLayout(FlowLayout.CENTER));
+ jpPassword.add(jlPassword);
+ jpPassword.add(jpfPassword);
+ jpPassword.setBorder(new EmptyBorder(5, 5, 5, 5));
+
+ JPanel jpButtons = new JPanel(new FlowLayout(FlowLayout.CENTER));
+ jpButtons.add(jbOK);
+ jpButtons.add(jbCancel);
+
+ getContentPane().add(jpPassword, BorderLayout.CENTER);
+ getContentPane().add(jpButtons, BorderLayout.SOUTH);
+
+ addWindowListener(new WindowAdapter()
+ {
+ public void windowClosing(WindowEvent evt)
+ {
+ closeDialog();
+ }
+ });
+
+ setResizable(false);
+
+ getRootPane().setDefaultButton(jbOK);
+
+ pack();
+ }
+
+ /**
+ * Check that the password entered is not empty and
+ * store the entered password.
+ */
+ private boolean checkPassword()
+ {
+ password = new String(jpfPassword.getPassword());
+
+
+ if (password.length() == 0) { //password is empty
+ JOptionPane.showMessageDialog(this,
+ "The password cannot be empty",
+ "Credential Manager Warning",
+ JOptionPane.WARNING_MESSAGE);
+ return false;
+ }
+ else { //password is not empty
+ return true;
+ }
+
+ }
+
+ /**
+ * OK button pressed or otherwise activated.
+ */
+ private void okPressed()
+ {
+ if (checkPassword()) {
+ closeDialog();
+ }
+ }
+
+ /**
+ * Cancel button pressed or otherwise activated.
+ */
+ private void cancelPressed()
+ {
+ password = null;
+ closeDialog();
+ }
+
+ /**
+ * Close the dialog.
+ */
+ private void closeDialog()
+ {
+ setVisible(false);
+ dispose();
+ }
+}
+
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/GetServiceURLDialog.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/GetServiceURLDialog.java
new file mode 100644
index 0000000..85c1c14
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/GetServiceURLDialog.java
@@ -0,0 +1,173 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager;
+
+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.JTextField;
+import javax.swing.border.EmptyBorder;
+
+/**
+ * Dialog used for entering a service URL.
+ *
+ * @author Alexandra Nenadic
+ */
+
+public class GetServiceURLDialog extends JDialog
+{
+
+ private static final long serialVersionUID = -2023348569964325951L;
+
+ // Password entry password field /
+ private JTextField jtfServiceURL;
+
+ // Stores the service URL entered /
+ private String serviceURL = null;
+
+ /**
+ * Creates new GetServiceURLDialog dialog where the parent is a frame.
+ */
+ public GetServiceURLDialog(JFrame parent, boolean modal)
+ {
+ super(parent, "Enter service URL", modal);
+ initComponents();
+ }
+
+ /**
+ * Creates new GetServiceURLDialog dialog where the parent is a dialog.
+ */
+ public GetServiceURLDialog(JDialog parent, boolean modal)
+ {
+ super(parent, "Enter service URL", modal);
+ initComponents();
+ }
+
+ /**
+ * Get the service URL set in the dialog.
+ *
+ * @return The service URL or null if none was set
+ */
+ public String getServiceURL()
+ {
+ return serviceURL;
+ }
+
+ /**
+ * Initialise the dialog's GUI components.
+ */
+ private void initComponents()
+ {
+ getContentPane().setLayout(new BorderLayout());
+
+ JLabel jlServiceURL = new JLabel("Service URL");
+ jtfServiceURL = new JTextField(15);
+
+ JButton jbOK = new JButton("OK");
+ jbOK.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent evt)
+ {
+ okPressed();
+ }
+ });
+
+ JButton jbCancel = new JButton("Cancel");
+ jbCancel.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent evt)
+ {
+ cancelPressed();
+ }
+ });
+
+
+ JLabel jlInstructions; // Instructions
+ jlInstructions = new JLabel ("Enter service URL for key pair");
+ jlInstructions.setFont(new Font(null, Font.PLAIN, 11));
+ jlInstructions.setBorder(new EmptyBorder(5,5,5,5));
+ getContentPane().add(jlInstructions, BorderLayout.NORTH);
+
+ JPanel jpServiceURL = new JPanel(new FlowLayout(FlowLayout.CENTER));
+ jpServiceURL.add(jlServiceURL);
+ jpServiceURL.add(jtfServiceURL);
+ jpServiceURL.setBorder(new EmptyBorder(5, 5, 5, 5));
+
+ JPanel jpButtons = new JPanel(new FlowLayout(FlowLayout.CENTER));
+ jpButtons.add(jbOK);
+ jpButtons.add(jbCancel);
+
+ getContentPane().add(jpServiceURL, BorderLayout.CENTER);
+ getContentPane().add(jpButtons, BorderLayout.SOUTH);
+
+ addWindowListener(new WindowAdapter()
+ {
+ public void windowClosing(WindowEvent evt)
+ {
+ closeDialog();
+ }
+ });
+
+ setResizable(false);
+
+ getRootPane().setDefaultButton(jbOK);
+
+ pack();
+ }
+
+ /**
+ * OK button pressed or otherwise activated.
+ */
+ private void okPressed()
+ {
+ serviceURL = new String(jtfServiceURL.getText());
+ closeDialog();
+ }
+
+ /**
+ * Cancel button pressed or otherwise activated.
+ */
+ private void cancelPressed()
+ {
+ serviceURL = null;
+ closeDialog();
+ }
+
+ /**
+ * Close the dialog.
+ */
+ private void closeDialog()
+ {
+ setVisible(false);
+ dispose();
+ }
+}
+
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/KeyPairsTableModel.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/KeyPairsTableModel.java
new file mode 100644
index 0000000..9688411
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/KeyPairsTableModel.java
@@ -0,0 +1,225 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager;
+
+import java.util.ArrayList;
+import java.util.TreeMap;
+
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.table.AbstractTableModel;
+
+import org.apache.log4j.Logger;
+
+import net.sf.taverna.t2.lang.observer.Observable;
+import net.sf.taverna.t2.lang.observer.Observer;
+import net.sf.taverna.t2.security.credentialmanager.CMException;
+import net.sf.taverna.t2.security.credentialmanager.CredentialManager;
+import net.sf.taverna.t2.security.credentialmanager.KeystoreChangedEvent;
+
+/**
+ * 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> {
+
+ // Column names
+ private String[] columnNames;
+
+ // Table data
+ private Object[][] data;
+
+ private CredentialManager credManager;
+
+ private Logger logger = Logger.getLogger(KeyPairsTableModel.class);
+
+ /**
+ * Construct a new KeyPairsTableModel.
+ */
+ public KeyPairsTableModel()
+ {
+ credManager = null;
+ try{
+ credManager = CredentialManager.getInstance();
+ }
+ catch (CMException cme){
+ // Failed to instantiate Credential Manager - warn the user and exit
+ String sMessage = "Failed to instantiate Credential Manager. " + cme.getMessage();
+ logger.error("CM GUI: "+ sMessage);
+ cme.printStackTrace();
+ JOptionPane.showMessageDialog(new JFrame(), sMessage,
+ "Credential Manager Error", JOptionPane.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.printStackTrace();
+ JOptionPane.showMessageDialog(new JFrame(), sMessage,
+ "Credential Manager Error", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ // Start observing changes to the Keystore
+ credManager.addObserver(this);
+ }
+
+ /**
+ * Load the KeyPairsTableModel with the key pair entries from the Keystore.
+ */
+ public void load() throws CMException {
+
+ try{
+ // Place key pair entries' aliases in a tree map to sort them
+ TreeMap<String, String> sortedAliases = new TreeMap<String, String>();
+
+ ArrayList<String> aliases = credManager.getAliases(CredentialManager.KEYSTORE);
+
+ for (String alias: aliases){
+ // 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] = CredentialManagerUI.KEY_PAIR_ENTRY_TYPE;
+
+ // Split the alias string to extract owner, issuer and serial number
+ // alias = "keypair#"<CERT_SUBJECT_COMMON_NAME>"#"<CERT_ISSUER_COMMON_NAME>"#"<CERT_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++;
+ }
+ }
+ catch (CMException cme){
+ throw (cme);
+ }
+
+ fireTableDataChanged();
+ }
+
+ /**
+ * Get the number of columns in the table.
+ */
+ public int getColumnCount()
+ {
+ return columnNames.length;
+ }
+
+ /**
+ * Get the number of rows in the table.
+ */
+ public int getRowCount()
+ {
+ return data.length;
+ }
+
+ /**
+ * Get the name of the column at the given position.
+ */
+ public String getColumnName(int iCol)
+ {
+ return columnNames[iCol];
+ }
+
+ /**
+ * Get the cell value at the given row and column position.
+ */
+ public Object getValueAt(int iRow, int iCol)
+ {
+ return data[iRow][iCol];
+ }
+
+ /**
+ * Get the class at of the cells at the given column position.
+ */
+ public Class<? extends Object> getColumnClass(int iCol)
+ {
+ return getValueAt(0, iCol).getClass();
+ }
+
+ /**
+ * Is the cell at the given row and column position editable?
+ */
+ public boolean isCellEditable(int iRow, int iCol)
+ {
+ // The table is always read-only
+ return false;
+ }
+
+ public void notify(Observable<KeystoreChangedEvent> sender,
+ KeystoreChangedEvent message) throws Exception {
+
+ // reload the table
+ if (message.keystoreType.equals(CredentialManager.KEYSTORE)){
+ load();
+ }
+ }
+
+}
+
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/NewEditPasswordEntryDialog.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/NewEditPasswordEntryDialog.java
new file mode 100644
index 0000000..536e06b
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/NewEditPasswordEntryDialog.java
@@ -0,0 +1,385 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager;
+
+import java.awt.BorderLayout;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+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 java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Set;
+
+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.JOptionPane;
+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 net.sf.taverna.t2.security.credentialmanager.CMException;
+import net.sf.taverna.t2.security.credentialmanager.CredentialManager;
+
+/**
+ * Dialog used for editing or entering new service URL, username or password of a password entry.
+ *
+ * @author Alex Nenadic
+ */
+@SuppressWarnings("serial")
+public class NewEditPasswordEntryDialog extends JDialog
+{
+ // '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 - NEW_MODE for entering new password entry and EDIT_MODE for editting an existing password entry */
+ String mode;
+
+ // Service URL field
+ private JTextField jtfServiceURL;
+
+ // Username field
+ private JTextField jtfUsername;
+
+ // First password entry field
+ private JPasswordField jpfFirstPassword;
+
+ // Password confirmation entry field
+ private JPasswordField jpfConfirmPassword;
+
+ // Stores service URL entered
+ private String serviceURL;
+
+ // Stores username entered
+ private String username;
+
+ // Stores password entered
+ private String password;
+
+ private Logger logger = Logger.getLogger(NewEditPasswordEntryDialog.class);
+
+ /**
+ * Creates new NewEditPasswordEntryDialog dialog where parent is a frame.
+ */
+ public NewEditPasswordEntryDialog(JFrame parent, String title,
+ boolean modal, String currentURL, String currentUsername,
+ String currentPassword)
+ {
+ super(parent, title, modal);
+ serviceURL = currentURL;
+ username = currentUsername;
+ password = currentPassword;
+ if (serviceURL == 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
+ }
+ initComponents();
+ }
+
+ /**
+ * Creates new NewEditPasswordEntryDialog dialog where parent is a dialog.
+ */
+ public NewEditPasswordEntryDialog(JDialog parent, String title, boolean modal, String currentURL, String currentUsername, String currentPassword)
+ {
+ super(parent, title, modal);
+ serviceURL = currentURL;
+ username = currentUsername;
+ password = currentPassword;
+ if (serviceURL == 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
+ }
+ initComponents();
+ }
+
+
+ /**
+ * Get the username set in the dialog.
+ *
+ * @return the username
+ */
+ public String getUsername()
+ {
+ return username;
+ }
+
+ /**
+ * Get the service URL set in the dialog.
+ *
+ * @return the service URL
+ */
+ public String getServiceURL()
+ {
+ return serviceURL;
+ }
+
+ /**
+ * Get the password set in the dialog.
+ *
+ * @return the password
+ */
+ public String getPassword()
+ {
+ return password;
+ }
+
+
+ /**
+ * Initialise the dialog's GUI components.
+ */
+ private void initComponents()
+ {
+ getContentPane().setLayout(new BorderLayout());
+
+ JLabel jlServiceURL = new JLabel("Service URL");
+ jlServiceURL.setBorder(new EmptyBorder(0,5,0,0));
+
+ JLabel jlUsername = new JLabel("Username");
+ jlUsername.setBorder(new EmptyBorder(0,5,0,0));
+
+ JLabel jlFirstPassword = new JLabel("Password");
+ jlFirstPassword.setBorder(new EmptyBorder(0,5,0,0));
+
+ JLabel jlConfirmPassword = new JLabel("Confirm password");
+ jlConfirmPassword.setBorder(new EmptyBorder(0,5,0,0));
+
+ jtfServiceURL = new JTextField(15);
+ //jtfServiceURL.setBorder(new EmptyBorder(0,0,0,5));
+
+ jtfUsername = new JTextField(15);
+ //jtfUsername.setBorder(new EmptyBorder(0,0,0,5));
+
+ jpfFirstPassword = new JPasswordField(15);
+ //jpfFirstPassword.setBorder(new EmptyBorder(0,0,0,5));
+
+ jpfConfirmPassword = 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)){
+ jtfServiceURL.setText(serviceURL);
+ jtfUsername.setText(username);
+ jpfFirstPassword.setText(password);
+ jpfConfirmPassword.setText(password);
+ }
+
+ JButton jbOK = new JButton("OK");
+ jbOK.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent evt)
+ {
+ okPressed();
+ }
+ });
+
+ JButton jbCancel = new JButton("Cancel");
+ jbCancel.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent evt)
+ {
+ cancelPressed();
+ }
+ });
+
+ JPanel jpPassword = new JPanel(new GridLayout(4, 2, 5, 5));
+ jpPassword.add(jlServiceURL);
+ jpPassword.add(jtfServiceURL);
+ jpPassword.add(jlUsername);
+ jpPassword.add(jtfUsername);
+ jpPassword.add(jlFirstPassword);
+ jpPassword.add(jpfFirstPassword);
+ jpPassword.add(jlConfirmPassword);
+ jpPassword.add(jpfConfirmPassword);
+
+ jpPassword.setBorder(new CompoundBorder(
+ new EmptyBorder(10, 10, 10, 10), new EtchedBorder()));
+
+ jpPassword.setMinimumSize(new Dimension(300,100));
+
+ JPanel jpButtons = new JPanel(new FlowLayout(FlowLayout.CENTER));
+ jpButtons.add(jbOK);
+ jpButtons.add(jbCancel);
+
+ getContentPane().add(jpPassword, BorderLayout.CENTER);
+ getContentPane().add(jpButtons, BorderLayout.SOUTH);
+
+ addWindowListener(new WindowAdapter()
+ {
+ public void windowClosing(WindowEvent evt)
+ {
+ closeDialog();
+ }
+ });
+
+ setResizable(false);
+
+ getRootPane().setDefaultButton(jbOK);
+
+ pack();
+ }
+
+ /**
+ * Checks for the following:
+ * <ul>
+ * <li>That the user has supplied a non empty service URL
+ * <li>That the user has supplied a non empty username
+ * <li>That the user has supplied and confirmed a non empty password
+ * <li>That the entry with the same URL already does not exist in the Keystore
+ * </ul>
+ * and stores the new password in this object.
+ *
+ * @return true - if the user's dialog entry matches the above criteria, false otherwise
+ */
+ private boolean checkControls()
+ {
+ serviceURL = new String(jtfServiceURL.getText());
+ if (serviceURL.length() == 0) {
+ JOptionPane.showMessageDialog(this,
+ "Service URL cannot be empty",
+ "Credential Manager Warning",
+ JOptionPane.WARNING_MESSAGE);
+
+ return false;
+ }
+
+ username = new String(jtfUsername.getText());
+ if (username.length() == 0){
+ JOptionPane.showMessageDialog(this,
+ "Username cannot be empty",
+ "Credential Manager Warning",
+ JOptionPane.WARNING_MESSAGE);
+
+ return false;
+ }
+
+ String sFirstPassword = new String(jpfFirstPassword.getPassword());
+ String sConfirmPassword = new String(jpfConfirmPassword.getPassword());
+
+ if ((sFirstPassword.length() > 0) && (sFirstPassword.equals(sConfirmPassword))) { // passwords the same and non-empty
+ password = sFirstPassword;
+ }
+ else if ((sFirstPassword.length() == 0) && (sFirstPassword.equals(sConfirmPassword))){ // passwords match but are empty
+
+ JOptionPane.showMessageDialog(this,
+ "Password cannot be empty",
+ "Credential Manager Warning",
+ JOptionPane.WARNING_MESSAGE);
+
+ return false;
+ }
+ else{ // passwords do not match
+ JOptionPane.showMessageDialog(this,
+ "Passwords do not match",
+ "Credential Manager Warning",
+ JOptionPane.WARNING_MESSAGE);
+
+ return false;
+ }
+
+ // Check if the entered URL is already associated with another key pair entry in the Keystore
+ CredentialManager credManager = null;
+ try {
+ credManager = CredentialManager.getInstance();
+ } catch (CMException cme) {
+ // Failed to instantiate Credential Manager - warn the user and exit
+ String exMessage = "Failed to instantiate Credential Manager";
+ logger.error(exMessage, cme);
+ cme.printStackTrace();
+ JOptionPane.showMessageDialog(new JFrame(), exMessage,
+ "Credential Manager Error", JOptionPane.ERROR_MESSAGE);
+ return false;
+ }
+
+ HashMap<String, ArrayList<String>> urlMap = credManager.getServiceURLsforKeyPairs();
+ if (urlMap != null){ // should not be null really (although can be empty). Check anyway.
+ Set<String> aliases = urlMap.keySet();
+ for (Iterator<String> i = aliases.iterator(); i.hasNext(); ){
+ String alias = (String) i.next();
+ // Check if url list for this alias contains the newly entered url
+ ArrayList<String> urls = (ArrayList<String>) urlMap.get(alias);
+ if (urls.contains(serviceURL)){
+ // Warn the user and exit
+ JOptionPane.showMessageDialog(
+ this,
+ "The entered URL is already associated with another key pair entry",
+ "Credential Manager Alert",
+ JOptionPane.INFORMATION_MESSAGE);
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * OK button pressed or otherwise activated.
+ */
+ private void okPressed()
+ {
+ if (checkControls()) {
+ closeDialog();
+ }
+ }
+
+ /**
+ * Cancel button pressed or otherwise activated.
+ */
+ private void cancelPressed()
+ {
+ // Set all fields to null to indicate that cancel button was pressed
+ serviceURL = null;
+ username = null;
+ password = null;
+ closeDialog();
+ }
+
+ /**
+ * Close the dialog.
+ */
+ private void closeDialog()
+ {
+ setVisible(false);
+ dispose();
+ }
+}
+
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/NewKeyPairEntryDialog.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/NewKeyPairEntryDialog.java
new file mode 100644
index 0000000..fac5e15
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/NewKeyPairEntryDialog.java
@@ -0,0 +1,564 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager;
+
+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.HashMap;
+import java.util.Set;
+import java.util.Iterator;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.DefaultListModel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.BoxLayout;
+import javax.swing.ListSelectionModel;
+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 net.sf.taverna.t2.security.credentialmanager.CMException;
+import net.sf.taverna.t2.security.credentialmanager.CMX509Util;
+import net.sf.taverna.t2.security.credentialmanager.CredentialManager;
+import net.sf.taverna.t2.workbench.ui.credentialmanager.GetServiceURLDialog;
+import net.sf.taverna.t2.workbench.ui.credentialmanager.ViewCertDetailsDialog;
+
+/**
+ * Dialog that displays the details of all key pairs from a PKCS #12
+ * keystore allowing the user to pick one for import.
+ *
+ * @author Alex Nenadic
+ */
+@SuppressWarnings("serial")
+class NewKeyPairEntryDialog extends JDialog
+{
+ // List of key pairs available for import
+ private JList jltKeyPairs;
+
+ // Service URL text field for user to enter
+ private JList jltServiceURLs;
+
+ // Service URL (associated with the key pair)
+ private ArrayList<String> serviceURLs;
+
+ // PKCS #12 keystore */
+ private KeyStore pkcs12KeyStore;
+
+ // Private key part of key pair chosen by the user for import
+ private Key privateKey;
+
+ // Certificate chain part of 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;
+
+ /**
+ * Creates new form NewKeyPairEntryDialog where the parent is a frame.
+ */
+ public NewKeyPairEntryDialog(JFrame parent, String title, boolean modal, KeyStore pkcs12KS)
+ throws CMException
+ {
+ super(parent, title, modal);
+ pkcs12KeyStore = pkcs12KS;
+ initComponents();
+ }
+
+ /**
+ * Creates new form NewKeyPairEntryDialog where the parent is a dialog.
+ */
+ public NewKeyPairEntryDialog(JDialog parent, String title, boolean modal, KeyStore pkcs12KS)
+ throws CMException
+ {
+ super(parent, title, modal);
+ pkcs12KeyStore = pkcs12KS;
+ initComponents();
+ }
+
+ /**
+ * Get the private part of the key pair chosen by the user for import.
+ *
+ * @return The private key or null if the user has not chosen a key pair
+ */
+ public Key getPrivateKey()
+ {
+ return privateKey;
+ }
+
+ /**
+ * Get the certificate chain part of the key pair chosen by the
+ * user for import.
+ *
+ * @return The certificate chain or null if the user has not
+ * chosen a key pair
+ */
+ public Certificate[] getCertificateChain()
+ {
+ return certificateChain;
+ }
+
+ /**
+ * Get the alias of the key pair chosen by the user for import.
+ *
+ * @return the alias
+ */
+ public String getAlias()
+ {
+ return alias;
+ }
+
+ /**
+ * Get the service URLs entered by the user.
+ *
+ * @return list of service URLs
+ */
+ public ArrayList<String> getServiceURLs()
+ {
+ return serviceURLs;
+ }
+
+ /**
+ * Initialise the dialog's GUI components.
+ *
+ * @throws CMException A problem was encountered importing a key pair
+ */
+ private void initComponents()
+ throws CMException
+ {
+ // Instructions
+ JLabel jlInstructions = new JLabel("Select a key pair for import:");
+ jlInstructions.setFont(new Font(null, Font.PLAIN, 11));
+ jlInstructions.setBorder(new EmptyBorder(5,5,5,5));
+ JPanel jpInstructions = new JPanel(new BorderLayout());
+ jpInstructions.add(jlInstructions, BorderLayout.WEST);
+
+ // Import button
+ final JButton jbImport = new JButton("Import");
+ jbImport.setEnabled(false);
+ jbImport.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent evt)
+ {
+ importPressed();
+ }
+ });
+
+ // Certificate details button
+ final JButton jbCertificateDetails = new JButton("Certificate Details");
+ jbCertificateDetails.setEnabled(false);
+ jbCertificateDetails.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent evt)
+ {
+ certificateDetailsPressed();
+ }
+ });
+
+ // List to hold keystore's key pairs
+ jltKeyPairs = new JList();
+ jltKeyPairs.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+ jltKeyPairs.addListSelectionListener(new ListSelectionListener()
+ {
+ public void valueChanged(ListSelectionEvent evt)
+ {
+ if (jltKeyPairs.getSelectedIndex() == -1) {
+ jbImport.setEnabled(false);
+ jbCertificateDetails.setEnabled(false);
+ }
+ else {
+ jbImport.setEnabled(true);
+ jbCertificateDetails.setEnabled(true);
+ }
+ }
+ });
+
+ // Put the key list into a scroll pane
+ JScrollPane jspKeyPairs = new JScrollPane(jltKeyPairs,
+ JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ jspKeyPairs.getViewport().setBackground(jltKeyPairs.getBackground());
+
+ // Service URLs list
+ // Label
+ JLabel jlServiceURL = new JLabel ("Service URLs the key pair will be used for:");
+ jlServiceURL.setFont(new Font(null, Font.PLAIN, 11));
+ jlServiceURL.setBorder(new EmptyBorder(5,5,5,5));
+ // New empty service URLs list
+ DefaultListModel jltModel = new DefaultListModel();
+ jltServiceURLs = new JList(jltModel);
+ // 'Add' service URL button
+ JButton addButton = new JButton("Add");
+ addButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent evt)
+ {
+ addServiceURLPressed();
+ }
+ });
+ addButton.setEnabled(true);
+ // 'Remove' service URL button
+ final JButton removeButton = new JButton("Remove");
+ removeButton.addActionListener(new ActionListener(){
+ public void actionPerformed(ActionEvent evt)
+ {
+ // get selected indices
+ int[] selected = jltServiceURLs.getSelectedIndices();
+ for (int i = selected.length -1; i>=0 ; i--){
+ ((DefaultListModel) jltServiceURLs.getModel()).remove(selected[i]);
+ }
+ }
+ });
+ removeButton.setEnabled(false);
+ jltServiceURLs.addListSelectionListener(new ListSelectionListener()
+ {
+ public void valueChanged(ListSelectionEvent evt)
+ {
+ if (jltServiceURLs.getSelectedIndex() == -1) {
+ removeButton.setEnabled(false);
+ }
+ else {
+ removeButton.setEnabled(true);
+ }
+ }
+ });
+ // Scroll pane for service URLs list
+ JScrollPane jspServiceURLs = new JScrollPane(jltServiceURLs,
+ JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ jspServiceURLs.getViewport().setBackground(jltServiceURLs.getBackground());
+
+ // Panel for Add and Remove buttons
+ JPanel jpServiceURLsButtons = new JPanel(new FlowLayout(FlowLayout.CENTER));
+ jpServiceURLsButtons.add(addButton);
+ jpServiceURLsButtons.add(removeButton);
+
+ // Panel to hold the list scroll pane and Add/Remove buttons panel
+ JPanel jpServiceURLs = new JPanel(new BorderLayout());
+ jpServiceURLs.add(jlServiceURL, BorderLayout.NORTH);
+ jpServiceURLs.add(jspServiceURLs, BorderLayout.CENTER);
+ jpServiceURLs.add(jpServiceURLsButtons, BorderLayout.SOUTH);
+
+ // Put all the key pair components together
+ JPanel jpKeyPairs = new JPanel(); // BoxLayout
+ jpKeyPairs.setLayout(new BoxLayout(jpKeyPairs, BoxLayout.Y_AXIS));
+ //jpKeyPairs.setPreferredSize(new Dimension(400, 200));
+ jpKeyPairs.setBorder(new CompoundBorder(new CompoundBorder(
+ new EmptyBorder(5, 5, 5, 5), new EtchedBorder()), new EmptyBorder(
+ 5, 5, 5, 5)));
+
+ jpInstructions.setAlignmentY(JPanel.LEFT_ALIGNMENT);
+ jpKeyPairs.add(jpInstructions);
+ jspKeyPairs.setAlignmentY(JPanel.LEFT_ALIGNMENT);
+ jpKeyPairs.add(jspKeyPairs);
+ jbCertificateDetails.setAlignmentY(JPanel.RIGHT_ALIGNMENT);
+ jpKeyPairs.add(jbCertificateDetails);
+ jpServiceURLs.setAlignmentY(JPanel.LEFT_ALIGNMENT);
+ jpKeyPairs.add(jpServiceURLs);
+
+ // Cancel button
+ final JButton jbCancel = new JButton("Cancel");
+ jbCancel.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent evt)
+ {
+ cancelPressed();
+ }
+ });
+
+ JPanel jpButtons = new JPanel(new FlowLayout(FlowLayout.CENTER));
+ jpButtons.add(jbImport);
+ jpButtons.add(jbCancel);
+
+ getContentPane().setLayout(new BorderLayout());
+ getContentPane().add(jpKeyPairs, BorderLayout.CENTER);
+ getContentPane().add(jpButtons, BorderLayout.SOUTH);
+
+ // Populate the list
+ populateList();
+
+ addWindowListener(new WindowAdapter()
+ {
+ public void windowClosing(WindowEvent evt)
+ {
+ closeDialog();
+ }
+ });
+
+ setResizable(false);
+
+ getRootPane().setDefaultButton(jbImport);
+
+ pack();
+
+ }
+
+ /**
+ * Populate the key pair list with the PKCS #12 keystore's key
+ * pair aliases.
+ *
+ * @throws CMException Problem accessing the keystore's entries
+ */
+ private void populateList()
+ throws CMException
+ {
+ try {
+ ArrayList<String> vKeyPairAliases = new ArrayList<String>();
+
+ // For each entry in the keystore...
+ for (Enumeration<String> aliases = pkcs12KeyStore.aliases(); aliases.hasMoreElements();)
+ {
+ // Get alias
+ String sAlias = (String) aliases.nextElement();
+
+ // Add the alias to the list if the entry has a key
+ // and certificates
+ if (pkcs12KeyStore.isKeyEntry(sAlias)) {
+ pkcs12KeyStore.getKey(sAlias, new char[] {});
+ Certificate[] certs = pkcs12KeyStore.getCertificateChain(sAlias);
+
+ if (certs != null && certs.length != 0) {
+ vKeyPairAliases.add(sAlias);
+ }
+ }
+ }
+
+ if (vKeyPairAliases.size() > 0) {
+ jltKeyPairs.setListData(vKeyPairAliases.toArray());
+ jltKeyPairs.setSelectedIndex(0);
+ }
+ else {
+ // No key pairs available...
+ jltKeyPairs.setListData(new String[] { "-- No key pairs present in the Credential Store --" });
+ jltKeyPairs.setEnabled(false);
+ }
+ }
+ catch (GeneralSecurityException ex) {
+ throw new CMException("Problem occured while accessing PKCS #12 keystore's entries.",
+ ex);
+ }
+ }
+
+ /**
+ * 'Certificate Details' button pressed. Display the selected key
+ * pair's certificate.
+ */
+ private void certificateDetailsPressed()
+ {
+ try {
+
+ String sAlias = (String) jltKeyPairs.getSelectedValue();
+
+ assert sAlias != null;
+
+ //Convert the certificate object into an X509Certificate object.
+ X509Certificate cert = CMX509Util.convertCertificate(pkcs12KeyStore.getCertificate(sAlias));
+
+ // Supply the certificate to the view certificate dialog
+ ViewCertDetailsDialog viewCertificateDialog = new ViewCertDetailsDialog(this,
+ "Certificate details",
+ true,
+ (X509Certificate) cert,
+ null);
+ viewCertificateDialog.setLocationRelativeTo(this);
+ viewCertificateDialog.setVisible(true);
+
+ }
+ catch (Exception ex) {
+
+ JOptionPane.showMessageDialog(this,
+ "Failed to obtain certificate details to show.",
+ "Credential Manager Alert",
+ JOptionPane.WARNING_MESSAGE);
+ closeDialog();
+ }
+ }
+
+
+ /**
+ * Import button pressed by user. Store the selected key pair's
+ * private and public parts and service URLs and close the dialog.
+ */
+ public void importPressed()
+ {
+ // Get Service URLs
+ serviceURLs = new ArrayList<String>();
+ Enumeration<?> URLs = (((DefaultListModel) jltServiceURLs.getModel()).elements());
+ for( ; URLs.hasMoreElements(); ){
+ serviceURLs.add((String) URLs.nextElement());
+ }
+
+ String sAlias = (String) jltKeyPairs.getSelectedValue();
+
+ assert sAlias != null;
+
+ try {
+ privateKey = pkcs12KeyStore.getKey(sAlias, new char[] {});
+ certificateChain = pkcs12KeyStore.getCertificateChain(sAlias);
+ alias = sAlias;
+ }
+ catch (Exception ex) {
+ JOptionPane.showMessageDialog(this,
+ "Failed to load the private key and certificate chain from PKCS #12 file.",
+ "Credential Manager Error",
+ JOptionPane.ERROR_MESSAGE);
+ closeDialog();
+ }
+
+ closeDialog();
+ }
+
+ /**
+ * Add Service URL button pressed.
+ */
+ public void addServiceURLPressed(){
+
+ // Display the dialog for entering service URL
+ GetServiceURLDialog dGetServiceURL = new GetServiceURLDialog(this, true);
+
+ dGetServiceURL.setLocationRelativeTo(this);
+ dGetServiceURL.setVisible(true);
+
+ String sURL = dGetServiceURL.getServiceURL();
+
+ if (sURL == null){ // user cancelled
+ return;
+ }
+
+ if (sURL.length() == 0){ // user entered an empty URL
+ // Warn the user
+ JOptionPane.showMessageDialog(
+ this,
+ "Service URL cannot be empty",
+ "Credential Manager Alert",
+ JOptionPane.INFORMATION_MESSAGE);
+ return;
+ }
+
+ // Check if the entered URL already exist in the URL list for this key entry
+ if (((DefaultListModel) jltServiceURLs.getModel()).contains(sURL)){
+
+ // Warn the user
+ JOptionPane.showMessageDialog(
+ this,
+ "The entered URL already exists in the list of URLs for this key pair entry",
+ "Credential Manager Alert",
+ JOptionPane.INFORMATION_MESSAGE);
+ return;
+ }
+
+ // Check if the entered URL is already associated with another key pair entry in the Keystore
+ CredentialManager credManager = null;
+ try {
+ credManager = CredentialManager.getInstance();
+ } catch (CMException cme) {
+ // Failed to instantiate Credential Manager - warn the user and exit
+ String sMessage = "Failed to instantiate Credential Manager. " + cme.getMessage();
+ cme.printStackTrace();
+ JOptionPane.showMessageDialog(new JFrame(), sMessage,
+ "Credential Manager Error", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ // Get the lists of URLs for the alias
+ HashMap<String, ArrayList<String>> serviceURLsMap = credManager.getServiceURLsforKeyPairs();
+ if (serviceURLsMap != null){ // should not be null really (although can be empty). Check anyway.
+ Set<String> aliases = serviceURLsMap.keySet();
+ for (Iterator<String> i = aliases.iterator(); i.hasNext(); ){
+ String alias = (String) i.next();
+ // Check if service URL list for this alias contains the newly entered URL
+ ArrayList<String> urls = (ArrayList<String>) serviceURLsMap.get(alias);
+ if (urls.contains(sURL)){
+ // Warn the user and exit
+ JOptionPane.showMessageDialog(
+ this,
+ "The entered URL is already associated with another key pair entry",
+ "Credential Manager Alert",
+ JOptionPane.INFORMATION_MESSAGE);
+ return;
+ }
+ }
+ }
+
+ // Check if the entered URL is already associated with a password entry in the Keystore
+// ArrayList<String> urlList = (ArrayList<String>) ((CredentialManagerUI) this.getParent()).getURLsForPasswords();
+// // Check if this url list contains the newly entered url
+// if (urlList.contains(sURL)){
+// // Warn the user and exit
+// JOptionPane.showMessageDialog(
+// this,
+// "The entered URL is already associated with a password entry",
+// "Credential Manager Alert",
+// JOptionPane.INFORMATION_MESSAGE);
+// return;
+// }
+
+ // Otherwise - the entered URL is not already associated with a different entry in the Keystore,
+ // so add this URL to the list of URLs for this key pair entry
+ ((DefaultListModel) jltServiceURLs.getModel()).addElement(sURL);
+ int index = ((DefaultListModel) jltServiceURLs.getModel()).getSize() - 1;
+ // Element is appended to the list - get its index
+ jltServiceURLs.setSelectedIndex(index);
+ // Insure the newly added URL is visible
+ jltServiceURLs.ensureIndexIsVisible(index);
+ }
+
+ /**
+ * Cancel button pressed - close the dialog.
+ */
+ 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;
+ serviceURLs = null;
+ closeDialog();
+ }
+
+ /**
+ * Closes the dialog.
+ */
+ private void closeDialog()
+ {
+ setVisible(false);
+ dispose();
+ }
+
+}
+
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/NewKeyPairServiceDialog.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/NewKeyPairServiceDialog.java
new file mode 100644
index 0000000..9c44eaf
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/NewKeyPairServiceDialog.java
@@ -0,0 +1,169 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager;
+
+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.JTextField;
+import javax.swing.border.EmptyBorder;
+
+/**
+ * Dialog used for entering service url.
+ *
+ * @author Alex Nenadic
+ */
+@SuppressWarnings("serial")
+public class NewKeyPairServiceDialog extends JDialog {
+ // Service URL entry field
+ private JTextField jtfServiceURL;
+
+ // Stores service URL entered
+ private String sURL = null;
+
+ /**
+ * Creates new NewKeyPairServiceDialog dialog where the parent is a frame.
+ */
+ public NewKeyPairServiceDialog(JFrame parent, String title, boolean modal)
+ {
+ super(parent, title, modal);
+ initComponents();
+ }
+
+ /**
+ * Creates new NewKeyPairServiceDialog dialog where the parent is a dialog.
+ */
+ public NewKeyPairServiceDialog(JDialog parent, String title, boolean modal)
+ {
+ super(parent, title, modal);
+ initComponents();
+ }
+
+ /**
+ * Get the service URL set in the dialog.
+ *
+ * @return The service URL or null if none was set
+ */
+ public String getServiceURL()
+ {
+ return sURL;
+ }
+
+ /**
+ * Initialise the dialog's GUI components.
+ */
+ private void initComponents()
+ {
+ getContentPane().setLayout(new BorderLayout());
+
+ JLabel jlDescription = new JLabel("Enter the service URL the key pair will be associated to");
+ jlDescription.setFont(new Font(null, Font.PLAIN, 11));
+ jlDescription.setBorder(new EmptyBorder(5,5,5,5));
+
+ JLabel jlServiceURL= new JLabel("Service URL");
+ jtfServiceURL = new JTextField(15);
+
+ JButton jbOK = new JButton("OK");
+ jbOK.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent evt)
+ {
+ okPressed();
+ }
+ });
+
+ JButton jbCancel = new JButton("Cancel");
+ jbCancel.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent evt)
+ {
+ cancelPressed();
+ }
+ });
+
+ JPanel jpServiceURL = new JPanel(new FlowLayout(FlowLayout.CENTER));
+ jpServiceURL.add(jlServiceURL);
+ jpServiceURL.add(jtfServiceURL);
+ jpServiceURL.setBorder(new EmptyBorder(5, 5, 5, 5));
+
+ JPanel jpButtons = new JPanel(new FlowLayout(FlowLayout.CENTER));
+ jpButtons.add(jbOK);
+ jpButtons.add(jbCancel);
+
+ getContentPane().add(jlDescription, BorderLayout.NORTH);
+ getContentPane().add(jpServiceURL, BorderLayout.CENTER);
+ getContentPane().add(jpButtons, BorderLayout.SOUTH);
+
+ addWindowListener(new WindowAdapter()
+ {
+ public void windowClosing(WindowEvent evt)
+ {
+ closeDialog();
+ }
+ });
+
+ setResizable(false);
+
+ getRootPane().setDefaultButton(jbOK);
+
+ pack();
+ }
+
+ /**
+ * OK button pressed or otherwise activated.
+ */
+ private void okPressed()
+ {
+ sURL = jtfServiceURL.getText();
+ closeDialog();
+ }
+
+ /**
+ * Cancel button pressed or otherwise activated.
+ */
+ private void cancelPressed()
+ {
+ // Set sURL field to null as it might have changed in the meantime
+ // if user entered some value than pressed cancel later on
+ sURL = null;
+ closeDialog();
+ }
+
+ /**
+ * Close the dialog.
+ */
+ private void closeDialog()
+ {
+ setVisible(false);
+ dispose();
+ }
+}
+
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/NewTrustCertsDialog.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/NewTrustCertsDialog.java
new file mode 100644
index 0000000..ec14b63
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/NewTrustCertsDialog.java
@@ -0,0 +1,296 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager;
+
+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.security.auth.x500.X500Principal;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JList;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.BoxLayout;
+import javax.swing.ListSelectionModel;
+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 net.sf.taverna.t2.security.credentialmanager.CMX509Util;
+import net.sf.taverna.t2.workbench.ui.credentialmanager.ViewCertDetailsDialog;
+
+/**
+ * Dialog that displays the details of all trusted certificates
+ * keystore allowing the user to pick one or more for import.
+ *
+ * @author Alex Nenadic
+ */
+class NewTrustCertsDialog
+ extends JDialog
+{
+
+ private static final long serialVersionUID = 8702957635188643993L;
+
+ /** List of trusted certs available for import */
+ private JList jltTrustCerts;
+
+ /** List of trusted certs available for import */
+ private ArrayList<X509Certificate> availableTrustCerts = new ArrayList<X509Certificate>();
+
+ /** List of trusted certs selected for import */
+ private ArrayList<X509Certificate> selectedTrustCerts;
+
+ /**
+ * Creates new form NewTrustCertsDialog where the parent is a frame.
+ */
+ public NewTrustCertsDialog(JFrame parent, String title, boolean modal, ArrayList<X509Certificate> lCerts)
+ {
+ super(parent, title, modal);
+ //System.arraycopy(lCerts, 0, trustCerts, 0, lCerts.length);
+ availableTrustCerts = lCerts;
+ initComponents();
+ }
+
+ /**
+ * Creates new form NewTrustCertsDialog where the parent is a frame.
+ */
+ public NewTrustCertsDialog(JDialog parent, String title, boolean modal, ArrayList<X509Certificate> lCerts)
+ {
+ super(parent, title, modal);
+ //System.arraycopy(lCerts, 0, trustCerts, 0, lCerts.length);
+ availableTrustCerts = lCerts;
+ initComponents();
+ }
+
+ /**
+ * Initialise the dialog's GUI components.
+ */
+ private void initComponents()
+ {
+ // Instructions
+ JLabel jlInstructions = new JLabel("Select one or more certificates for import:");
+ jlInstructions.setFont(new Font(null, Font.PLAIN, 11));
+ jlInstructions.setBorder(new EmptyBorder(5,5,5,5));
+ JPanel jpInstructions = new JPanel(new BorderLayout());
+ jpInstructions.add(jlInstructions, BorderLayout.WEST);
+
+ // Import button
+ final JButton jbImport = new JButton("Import");
+ jbImport.setEnabled(false);
+ jbImport.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent evt)
+ {
+ importPressed();
+ }
+ });
+
+ // Certificate details button
+ final JButton jbCertificateDetails = new JButton("Certificate Details");
+ jbCertificateDetails.setEnabled(false);
+ jbCertificateDetails.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent evt)
+ {
+ certificateDetailsPressed();
+ }
+ });
+
+ // List to hold trusted certs' aliases
+ jltTrustCerts = new JList();
+ jltTrustCerts.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION );
+ jltTrustCerts.addListSelectionListener(new ListSelectionListener()
+ {
+ public void valueChanged(ListSelectionEvent evt)
+ {
+
+ if (jltTrustCerts.getSelectedIndex() == -1) {
+ jbImport.setEnabled(false);
+ jbCertificateDetails.setEnabled(false);
+ }
+ else {
+ jbImport.setEnabled(true);
+ jbCertificateDetails.setEnabled(true);
+ }
+ }
+ });
+ // Populate the list
+ // Get the certificate subjects' CNs
+ ArrayList<String> cns = new ArrayList<String>();
+ for (int i = 0; i < availableTrustCerts.size(); i++){
+
+ String DN = ((X509Certificate) availableTrustCerts.get(i)).getSubjectX500Principal().getName(X500Principal.RFC2253);
+ CMX509Util util = new CMX509Util();
+ util.parseDN(DN);
+
+ String CN = util.getCN();
+ cns.add(i, CN);
+ }
+ jltTrustCerts.setListData(cns.toArray());
+ jltTrustCerts.setSelectedIndex(0);
+
+ // Put the list into a scroll pane
+ JScrollPane jspTrustCerts = new JScrollPane(jltTrustCerts,
+ JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ jspTrustCerts.getViewport().setBackground(jltTrustCerts.getBackground());
+
+ // Put all the trusted cert components together
+ JPanel jpTrustCerts = new JPanel(); // BoxLayout
+ jpTrustCerts.setLayout(new BoxLayout(jpTrustCerts, BoxLayout.Y_AXIS));
+ //jpKeyPairs.setPreferredSize(new Dimension(400, 200));
+ jpTrustCerts.setBorder(new CompoundBorder(new CompoundBorder(
+ new EmptyBorder(5, 5, 5, 5), new EtchedBorder()), new EmptyBorder(
+ 5, 5, 5, 5)));
+
+ jpInstructions.setAlignmentY(JPanel.LEFT_ALIGNMENT);
+ jpTrustCerts.add(jpInstructions);
+ jspTrustCerts.setAlignmentY(JPanel.LEFT_ALIGNMENT);
+ jpTrustCerts.add(jspTrustCerts);
+ jbCertificateDetails.setAlignmentY(JPanel.RIGHT_ALIGNMENT);
+ jpTrustCerts.add(jbCertificateDetails);
+
+ // Cancel button
+ final JButton jbCancel = new JButton("Cancel");
+ jbCancel.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent evt)
+ {
+ cancelPressed();
+ }
+ });
+
+ JPanel jpButtons = new JPanel(new FlowLayout(FlowLayout.CENTER));
+ jpButtons.add(jbImport);
+ jpButtons.add(jbCancel);
+
+ getContentPane().setLayout(new BorderLayout());
+ getContentPane().add(jpTrustCerts, BorderLayout.CENTER);
+ getContentPane().add(jpButtons, BorderLayout.SOUTH);
+
+ addWindowListener(new WindowAdapter()
+ {
+ public void windowClosing(WindowEvent evt)
+ {
+ closeDialog();
+ }
+ });
+
+ setResizable(false);
+
+ getRootPane().setDefaultButton(jbImport);
+
+ pack();
+
+ }
+
+ /**
+ * Certificate Details button pressed. Display the selected key
+ * pair's certificate.
+ */
+ private void certificateDetailsPressed()
+ {
+ try {
+
+ int i = jltTrustCerts.getSelectedIndex();
+
+ X509Certificate cert = (X509Certificate) availableTrustCerts.get(i);
+
+ // Supply the certificate to the view certificate dialog
+ ViewCertDetailsDialog viewCertificateDialog = new ViewCertDetailsDialog(this,
+ "Certificate details",
+ true,
+ cert,
+ null);
+ viewCertificateDialog.setLocationRelativeTo(this);
+ viewCertificateDialog.setVisible(true);
+
+ }
+ catch (Exception ex) {
+ JOptionPane.showMessageDialog(this,
+ "Failed to obtain certificate details to show.",
+ "Credential Manager Alert",
+ JOptionPane.WARNING_MESSAGE);
+ closeDialog();
+
+ }
+ }
+
+ /**
+ * Get the trusted certificates selected for import.
+ *
+ * @return The array of trusted certificates selected for import
+ */
+ public ArrayList<X509Certificate> getTrustedCertificates()
+ {
+ return selectedTrustCerts;
+ }
+
+
+ /**
+ * Import button pressed by user. Store the selected trusted certs
+ * and close the dialog.
+ */
+ public void importPressed()
+ {
+ int[] selectedValues = jltTrustCerts.getSelectedIndices();
+ selectedTrustCerts = new ArrayList<X509Certificate>();
+ for (int i= 0; i < selectedValues.length; i++){
+ selectedTrustCerts.add(availableTrustCerts.get(selectedValues[i]));
+ }
+
+ closeDialog();
+ }
+
+
+ /**
+ * Cancel button pressed - close the dialog.
+ */
+ public void cancelPressed()
+ {
+ // Set selectedTrustCerts to null to indicate that user cancelled
+ selectedTrustCerts = null;
+ closeDialog();
+ }
+
+ /**
+ * Closes the dialog.
+ */
+ private void closeDialog()
+ {
+ setVisible(false);
+ dispose();
+ }
+}
+
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/PasswordsTableModel.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/PasswordsTableModel.java
new file mode 100644
index 0000000..155b946
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/PasswordsTableModel.java
@@ -0,0 +1,227 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager;
+
+import java.util.ArrayList;
+import java.util.TreeMap;
+
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.table.AbstractTableModel;
+
+import net.sf.taverna.t2.lang.observer.Observable;
+import net.sf.taverna.t2.lang.observer.Observer;
+import net.sf.taverna.t2.security.credentialmanager.CMException;
+import net.sf.taverna.t2.security.credentialmanager.CredentialManager;
+import net.sf.taverna.t2.security.credentialmanager.KeystoreChangedEvent;
+import net.sf.taverna.t2.workbench.ui.credentialmanager.CredentialManagerUI;
+
+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> {
+
+ // Column names
+ private String[] columnNames;
+
+ // Table data
+ private Object[][] data;
+
+ private CredentialManager credManager;
+
+ private Logger logger = Logger.getLogger(PasswordsTableModel.class);
+
+ /**
+ * Construct a new PasswordsTableModel.
+ */
+ public PasswordsTableModel(){
+
+ credManager = null;
+ try{
+ credManager = CredentialManager.getInstance();
+ }
+ catch (CMException cme){
+ // Failed to instantiate Credential Manager - warn the user and exit
+ String sMessage = "Failed to instantiate Credential Manager. " + cme.getMessage();
+ logger.error("CM GUI: "+ sMessage);
+ cme.printStackTrace();
+ JOptionPane.showMessageDialog(new JFrame(), sMessage,
+ "Credential Manager Error", JOptionPane.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);
+ cme.printStackTrace();
+ JOptionPane.showMessageDialog(new JFrame(), sMessage,
+ "Credential Manager Error", JOptionPane.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
+ {
+ try{
+ // Place password entries' aliases in a tree map to sort them
+ TreeMap<String, String> sortedAliases = new TreeMap<String, String>();
+
+ ArrayList<String> aliases = credManager.getAliases(CredentialManager.KEYSTORE);
+
+ for (String alias: aliases){
+ // 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#")){
+ sortedAliases.put(alias, alias);
+ }
+ }
+
+ // Create one table row for each password entry
+ data = new Object[sortedAliases.size()][6];
+
+ // Iterate through the sorted aliases, retrieving the password
+ // 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] = CredentialManagerUI.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> <PASSWORD>
+ String unpassPair = credManager.getUsernameAndPasswordForService(serviceURL);
+ String username = unpassPair.substring(0, unpassPair.indexOf(' '));
+ String password = unpassPair.substring(unpassPair.indexOf(' ')+1);
+
+ // 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();
+ }
+ catch (CMException cme){
+ throw cme;
+ }
+ }
+
+ /**
+ * Get the number of columns in the table.
+ */
+ public int getColumnCount()
+ {
+ return columnNames.length;
+ }
+
+ /**
+ * Get the number of rows in the table.
+ */
+ public int getRowCount()
+ {
+ return data.length;
+ }
+
+ /**
+ * Get the name of the column at the given position.
+ */
+ public String getColumnName(int iCol)
+ {
+ return columnNames[iCol];
+ }
+
+ /**
+ * Get the cell value at the given row and column position.
+ */
+ public Object getValueAt(int iRow, int iCol)
+ {
+ return data[iRow][iCol];
+ }
+
+ /**
+ * Get the class at of the cells at the given column position.
+ */
+ public Class<? extends Object> getColumnClass(int iCol)
+ {
+ return getValueAt(0, iCol).getClass();
+ }
+
+ /**
+ * Is the cell at the given row and column position editable?
+ */
+ public boolean isCellEditable(int iRow, int iCol)
+ {
+ // The table is always read-only
+ return false;
+ }
+
+ public void notify(Observable<KeystoreChangedEvent> sender,
+ KeystoreChangedEvent message) throws Exception {
+
+ // reload the table
+ if (message.keystoreType.equals(CredentialManager.KEYSTORE)){
+ load();
+ }
+ }
+
+}
+
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/ProxiesTableModel.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/ProxiesTableModel.java
new file mode 100644
index 0000000..fb8c998
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/ProxiesTableModel.java
@@ -0,0 +1,233 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager;
+
+import java.math.BigInteger;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.TreeMap;
+
+import javax.security.auth.x500.X500Principal;
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.table.AbstractTableModel;
+
+import org.apache.log4j.Logger;
+
+import net.sf.taverna.t2.lang.observer.Observable;
+import net.sf.taverna.t2.lang.observer.Observer;
+import net.sf.taverna.t2.security.credentialmanager.CMException;
+import net.sf.taverna.t2.security.credentialmanager.CMX509Util;
+import net.sf.taverna.t2.security.credentialmanager.CredentialManager;
+import net.sf.taverna.t2.security.credentialmanager.KeystoreChangedEvent;
+
+/**
+ * The table model used to display the Keystore's proxy key pair entries.
+ *
+ * @author Alex Nenadic
+ */
+@SuppressWarnings("serial")
+public class ProxiesTableModel extends AbstractTableModel implements Observer<KeystoreChangedEvent> {
+
+ // Column names
+ private String[] columnNames;
+
+ // Table data
+ private Object[][] data;
+
+ private CredentialManager credManager;
+
+ private Logger logger = Logger.getLogger(KeyPairsTableModel.class);
+
+ /**
+ * Construct a new KeyPairsTableModel.
+ */
+ public ProxiesTableModel()
+ {
+ credManager = null;
+ try{
+ credManager = CredentialManager.getInstance();
+ }
+ catch (CMException cme){
+ // Failed to instantiate Credential Manager - warn the user and exit
+ String sMessage = "Failed to instantiate Credential Manager. " + cme.getMessage();
+ logger.error("CM GUI: "+ sMessage);
+ cme.printStackTrace();
+ JOptionPane.showMessageDialog(new JFrame(), sMessage,
+ "Credential Manager Error", JOptionPane.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
+ "Alias", // the invisible column holding the actual alias in the Keystore
+ };
+
+ try {
+ load();
+ } catch (CMException cme) {
+ String sMessage = "Failed to load proxies";
+ logger.error(sMessage);
+ cme.printStackTrace();
+ JOptionPane.showMessageDialog(new JFrame(), sMessage,
+ "Credential Manager Error", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ // Start observing changes to the Keystore
+ credManager.addObserver(this);
+ }
+
+ /**
+ * Load the ProxiesTableModel with the proxy entries from the Keystore.
+ */
+ public void load() throws CMException {
+
+ try{
+ // Place proxy entries' aliases in a tree map to sort them
+ TreeMap<String, String> sortedAliases = new TreeMap<String, String>();
+
+ ArrayList<String> aliases = credManager.getAliases(CredentialManager.KEYSTORE);
+
+ for (String alias: aliases){
+ // We are only interested in proxy entries here.
+ // Alias for such entries is constructed as "proxy#<CERT_SERIAL_NUMBER>#<CERT_COMMON_NAME>" where
+ if (alias.startsWith("cagridproxy#") || alias.startsWith("proxy#")){ // for different proxies
+ sortedAliases.put(alias, alias);
+ }
+ }
+
+ // Create one table row for each proxy entry
+ data = new Object[sortedAliases.size()][6];
+
+ // Iterate through the sorted aliases (if any), retrieving the proxy
+ // entries and populating the table model
+ int iCnt = 0;
+ for (String alias : sortedAliases.values())
+ {
+ if (alias.startsWith("cagridproxy#")){
+
+ // 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] = CredentialManagerUI.PROXY_ENTRY_TYPE;
+
+ X509Certificate cert = CMX509Util.convertCertificate(credManager.getCertificate(CredentialManager.KEYSTORE, alias));
+
+ // Populate the "Owner:Serial Number" column extracted from the alias
+ String ownerDN = cert.getSubjectX500Principal().getName(X500Principal.RFC2253);
+ CMX509Util util = new CMX509Util();
+ util.parseDN(ownerDN);
+ data[iCnt][1] = util.getCN(); // owner's common name
+
+ // Populate the issuer column
+ String issuerDN = cert.getIssuerX500Principal().getName(X500Principal.RFC2253);
+ util.parseDN(issuerDN);
+ data[iCnt][2] = util.getCN();
+
+ // Get the hexadecimal representation of the certificate's serial number
+ String serialNumber = new BigInteger(1, cert.getSerialNumber().toByteArray()).toString(16).toUpperCase();
+ data[iCnt][3] = serialNumber;
+
+ // Populate the modified date column ("UBER" keystore type supports creation date)
+ data[iCnt][4] = credManager.getEntryCreationDate(CredentialManager.KEYSTORE, alias);
+
+ // Populate the invisible alias column
+ data[iCnt][5] = alias;
+
+ iCnt++;
+ }
+ // else if (alias.startsWith("proxy#")) {} // for some other proxies
+ }
+ }
+ catch (CMException cme){
+ throw (cme);
+ }
+
+ fireTableDataChanged();
+ }
+
+ /**
+ * Get the number of columns in the table.
+ */
+ public int getColumnCount()
+ {
+ return columnNames.length;
+ }
+
+ /**
+ * Get the number of rows in the table.
+ */
+ public int getRowCount()
+ {
+ return data.length;
+ }
+
+ /**
+ * Get the name of the column at the given position.
+ */
+ public String getColumnName(int iCol)
+ {
+ return columnNames[iCol];
+ }
+
+ /**
+ * Get the cell value at the given row and column position.
+ */
+ public Object getValueAt(int iRow, int iCol)
+ {
+ return data[iRow][iCol];
+ }
+
+ /**
+ * Get the class at of the cells at the given column position.
+ */
+ public Class<? extends Object> getColumnClass(int iCol)
+ {
+ return getValueAt(0, iCol).getClass();
+ }
+
+ /**
+ * Is the cell at the given row and column position editable?
+ */
+ public boolean isCellEditable(int iRow, int iCol)
+ {
+ // The table is always read-only
+ return false;
+ }
+
+ public void notify(Observable<KeystoreChangedEvent> sender,
+ KeystoreChangedEvent message) throws Exception {
+
+ // reload the table
+ if (message.keystoreType.equals(CredentialManager.KEYSTORE)){
+ load();
+ }
+ }
+
+}
+
+
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/TableCellRenderer.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/TableCellRenderer.java
new file mode 100644
index 0000000..8db788d
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/TableCellRenderer.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager;
+
+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.CredentialManagerUI;
+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.TableCellRenderer;
+import net.sf.taverna.t2.workbench.ui.credentialmanager.TrustedCertsTableModel;
+
+/**
+ * Custom cell renderer for the cells of the tables displaying Keystore/Truststore contents.
+ *
+ * @author Alexandra 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"));
+
+ /**
+ * Returns the rendered cell for the supplied value and column.
+ *
+ * @param jtKeyStore The JTable
+ * @param value The value to assign to the cell
+ * @param bIsSelected True if cell is selected
+ * @param iRow The row of the cell to render
+ * @param iCol The column of the cell to render
+ * @param bHasFocus If true, render cell appropriately
+ * @return The renderered cell
+ */
+ public Component getTableCellRendererComponent(JTable jtKeyStoreTable,
+ Object value, boolean bIsSelected, boolean bHasFocus, int iRow,
+ int iCol)
+ {
+ JLabel cell = (JLabel) super.getTableCellRendererComponent(jtKeyStoreTable,
+ value, bIsSelected, bHasFocus, iRow, iCol);
+
+ if (value != null){
+ // Type column - display an icon representing the type
+ if (iCol == 0) {
+ ImageIcon icon = null;
+ //The cell is in the first column of Passwords table
+ if (CredentialManagerUI.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 (CredentialManagerUI.KEY_PAIR_ENTRY_TYPE.equals(value)) {
+ icon = keypairEntryIcon; //key pair entry image
+ }
+ // The cell is in the first column of Proxies table
+ else if (CredentialManagerUI.PROXY_ENTRY_TYPE.equals(value)) {
+ icon = keypairEntryIcon; //key pair entry image
+ }
+ //The cell is in the first column of Trusted Certificates table
+ else if (CredentialManagerUI.TRUST_CERT_ENTRY_TYPE.equals(value)) {
+ icon = trustcertEntryIcon; //trust. certificate entry image
+ }
+
+ cell.setIcon(icon);
+ cell.setText("");
+ cell.setVerticalAlignment(CENTER);
+ cell.setHorizontalAlignment(CENTER);
+
+ }
+ // Last Modified column - format date (if date supplied)
+ else if (((jtKeyStoreTable.getModel() instanceof PasswordsTableModel) && (iCol == 3)) ||
+ ((jtKeyStoreTable.getModel() instanceof KeyPairsTableModel) && (iCol == 4))||
+ ((jtKeyStoreTable.getModel() instanceof ProxiesTableModel) && (iCol == 4))||
+ ((jtKeyStoreTable.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
+ else {
+ cell.setText(value.toString());
+ }
+ }
+
+ cell.setBorder(new EmptyBorder(0, 5, 0, 5));
+
+ return cell;
+ }
+}
+
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/TableHeaderRenderer.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/TableHeaderRenderer.java
new file mode 100644
index 0000000..2fc6cb9
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/TableHeaderRenderer.java
@@ -0,0 +1,142 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager;
+
+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;
+
+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.TableHeaderRenderer;
+import net.sf.taverna.t2.workbench.ui.credentialmanager.TrustedCertsTableModel;
+
+/**
+ * Custom cell renderer for the headers of the tables displaying Keystore/Truststore contents.
+ *
+ * @author Alexandra Nenadic
+ */
+@SuppressWarnings("serial")
+public class TableHeaderRenderer extends DefaultTableCellRenderer {
+
+ private final ImageIcon entryTypeIcon = new ImageIcon(TableHeaderRenderer.class.getResource(
+ "/images/table/entry_heading.png"));
+
+ /**
+ * Returns the rendered header cell for the supplied value and column.
+ *
+ * @param jtKeyStore The JTable
+ * @param value The value to assign to the cell
+ * @param bIsSelected True if cell is selected
+ * @param iRow The row of the cell to render
+ * @param iCol The column of the cell to render
+ * @param bHasFocus If true, render cell appropriately
+ ** @return The renderered cell
+ */
+ 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
+ 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 has 5 colums, Key pairs and Trusted Certificates tables have 3 each
+ 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");
+ }
+ else if (iCol == 3){ // Last modified column
+ header.setToolTipText("Last modification date and time");
+ }
+ }
+ 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");
+ }
+ else if(iCol == 4) { // Last modified column
+ header.setToolTipText("Last modification date and time");
+ }
+ }
+ else if(jtKeyStoreTable.getModel() instanceof ProxiesTableModel){
+ 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");
+ }
+ else if(iCol == 4) { // Last modified column
+ header.setToolTipText("Last modification date and time");
+ }
+ }
+ 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");
+ }
+ else if(iCol == 4) { // Last modified column
+ header.setToolTipText("Last modification date and time");
+ }
+ }
+ }
+ header.setBorder(new CompoundBorder(
+ new BevelBorder(BevelBorder.RAISED), new EmptyBorder(0, 5, 0, 5)));
+
+ return header;
+ }
+}
+
+
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/TrustedCertsTableModel.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/TrustedCertsTableModel.java
new file mode 100644
index 0000000..7d7da07
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/TrustedCertsTableModel.java
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager;
+
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.table.AbstractTableModel;
+
+import org.apache.log4j.Logger;
+
+import net.sf.taverna.t2.lang.observer.Observable;
+import net.sf.taverna.t2.lang.observer.Observer;
+import net.sf.taverna.t2.security.credentialmanager.CMException;
+import net.sf.taverna.t2.security.credentialmanager.CredentialManager;
+import net.sf.taverna.t2.security.credentialmanager.KeystoreChangedEvent;
+
+import java.util.ArrayList;
+import java.util.TreeMap;
+
+/**
+ * The table model used to display the Keystore's trusted certificate entries.
+ *
+ * @author Alex Nenadic
+ */
+@SuppressWarnings("serial")
+public class TrustedCertsTableModel extends AbstractTableModel implements Observer<KeystoreChangedEvent>{
+
+ // Column names
+ private String[] columnNames;
+
+ // Table data
+ private Object[][] data;
+
+ private CredentialManager credManager;
+
+ private Logger logger = Logger.getLogger(TrustedCertsTableModel.class);
+
+
+ /**
+ * Construct a new TrustCertsTableModel.
+ */
+ public TrustedCertsTableModel() {
+ credManager = null;
+ try{
+ credManager = CredentialManager.getInstance();
+ }
+ catch (CMException cme){
+ // Failed to instantiate Credential Manager - warn the user and exit
+ String sMessage = "Failed to instantiate Credential Manager. " + cme.getMessage();
+ logger.error("CM GUI: "+ sMessage);
+ cme.printStackTrace();
+ JOptionPane.showMessageDialog(new JFrame(), sMessage,
+ "Credential Manager Error", JOptionPane.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
+ "Alias" // the invisible column holding the actual alias in the Keystore
+ };
+
+ try {
+ load();
+ } catch (CMException cme) {
+ String sMessage = "Failed to load trusted certificates";
+ logger.error(sMessage);
+ cme.printStackTrace();
+ JOptionPane.showMessageDialog(new JFrame(), sMessage,
+ "Credential Manager Error", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ // Start observing changes to the Keystore
+ credManager.addObserver(this);
+ }
+
+ /**
+ * Load the TrustCertsTableModel with trusted certificate entries from the Keystore.
+ */
+ public void load() throws CMException {
+ try{
+ // Place trusted certificate entries' aliases in a tree map to sort them
+ TreeMap<String, String> sortedAliases = new TreeMap<String, String>();
+
+ ArrayList<String> aliases = credManager.getAliases(CredentialManager.TRUSTSTORE);
+
+ for (String alias: aliases){
+ // We are only interested in trusted certificate entries here.
+ // Alias for such entries is constructed as "trustedcert#<CERT_SERIAL_NUMBER>#<CERT_COMMON_NAME>"
+ if (alias.startsWith("trustedcert#")){
+ sortedAliases.put(alias, alias);
+ }
+ }
+
+ // Create one table row for each trusted certificate entry
+ // Each row has 4 fields - type, owner name, last modified data and the invisible alias
+ data = new Object[sortedAliases.size()][6];
+
+ // Iterate through the sorted aliases, retrieving the trusted certificate
+ // 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] = CredentialManagerUI.TRUST_CERT_ENTRY_TYPE;
+
+ // Split the alias string to extract owner, issuer and serial number
+ // alias = "trustedcert#<CERT_SUBJECT_COMMON_NAME>"#"<CERT_ISSUER_COMMON_NAME>"#"<CERT_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
+ data[iCnt][4] = credManager.getEntryCreationDate(CredentialManager.TRUSTSTORE, alias);
+
+ // Populate the invisible alias column
+ data[iCnt][5] = alias;
+
+ iCnt ++;
+ }
+ }
+ catch (CMException cme){
+ throw (cme);
+ }
+
+ fireTableDataChanged();
+ }
+
+ /**
+ * Get the number of columns in the table.
+ *
+ * @return The number of columns
+ */
+ public int getColumnCount()
+ {
+ return columnNames.length;
+ }
+
+ /**
+ * Get the number of rows in the table.
+ *
+ * @return The number of rows
+ */
+ public int getRowCount()
+ {
+ return data.length;
+ }
+
+ /**
+ * Get the name of the column at the given position.
+ *
+ * @param iCol The column position
+ * @return The column name
+ */
+ public String getColumnName(int iCol)
+ {
+ return columnNames[iCol];
+ }
+
+ /**
+ * Get the cell value at the given row and column position.
+ *
+ * @param iRow The row position
+ * @param iCol The column position
+ * @return The cell value
+ */
+ public Object getValueAt(int iRow, int iCol)
+ {
+ return data[iRow][iCol];
+ }
+
+ /**
+ * Get the class at of the cells at the given column position.
+ *
+ * @param iCol The column position
+ * @return The column cells' class
+ */
+ public Class<? extends Object> getColumnClass(int iCol)
+ {
+ return getValueAt(0, iCol).getClass();
+ }
+
+ /**
+ * Is the cell at the given row and column position editable?
+ *
+ * @param iRow The row position
+ * @param iCol The column position
+ * @return True if the cell is editable, false otherwise
+ */
+ public boolean isCellEditable(int iRow, int iCol)
+ {
+ // The table is always read-only
+ return false;
+ }
+
+ public void notify(Observable<KeystoreChangedEvent> sender,
+ KeystoreChangedEvent message) throws Exception {
+
+ // reload the table
+ if (message.keystoreType.equals(CredentialManager.TRUSTSTORE)){
+ load();
+ }
+ }
+
+}
+
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/ViewCaGridProxyCertDetailsDialog.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/ViewCaGridProxyCertDetailsDialog.java
new file mode 100644
index 0000000..1ce72ce
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/ViewCaGridProxyCertDetailsDialog.java
@@ -0,0 +1,600 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.FlowLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+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.math.BigInteger;
+import java.util.HashMap;
+
+import javax.swing.BoxLayout;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.SwingUtilities;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.EtchedBorder;
+import javax.swing.JSeparator;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import javax.security.auth.x500.X500Principal;
+
+import net.sf.taverna.t2.security.credentialmanager.CMException;
+import net.sf.taverna.t2.security.credentialmanager.CMX509Util;
+
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.DERBitString;
+import org.bouncycastle.asn1.DEROctetString;
+import org.bouncycastle.asn1.misc.NetscapeCertType;
+
+
+/**
+ * Displays the details of a X.509 caGrid proxy certificate.
+ *
+ * @author Alex Nenadic
+ */
+@SuppressWarnings("serial")
+public class ViewCaGridProxyCertDetailsDialog extends JDialog {
+
+ // Logger
+ //private static Logger logger = Logger.getLogger(ViewCertDetailsDialog.class);
+
+ // Stores certificate to display
+ private X509Certificate cert;
+
+ private String authNServiceURL;
+
+ private String dorianServiceURL;
+
+
+ /**
+ * Creates new ViewCaGridProxyCertDialog dialog where the parent is a frame.
+ */
+ public ViewCaGridProxyCertDetailsDialog(JFrame parent, String title, boolean modal,
+ X509Certificate crt, String authNServiceURL, String dorianServiceURL)
+ throws CMException
+ {
+ super(parent, title, modal);
+ this.cert = crt;
+ this.authNServiceURL = authNServiceURL;
+ this.dorianServiceURL = dorianServiceURL;
+ initComponents();
+ }
+
+ /**
+ * Creates new ViewCaGridProxyCertDialog dialog where the parent is a dialog.
+ */
+ public ViewCaGridProxyCertDetailsDialog(JDialog parent, String title, boolean modal,
+ X509Certificate crt, String authNServiceURL, String dorianServiceURL)
+ throws CMException
+ {
+ super(parent, title, modal);
+ cert = crt;
+ this.authNServiceURL = authNServiceURL;
+ this.dorianServiceURL = dorianServiceURL;
+ initComponents();
+ }
+
+ /**
+ * Initialise the dialog's GUI components.
+ *
+ * @throws CMException A problem was encountered getting the
+ * certificates' details
+ */
+ private void initComponents()
+ throws CMException
+ {
+
+ // Certificate details:
+
+ // Grid Bag Constraints templates for labels (column 1) and
+ // values (column 2) of certificate details
+ GridBagConstraints gbcLabel = new GridBagConstraints();
+ gbcLabel.gridx = 0;
+ gbcLabel.ipadx = 20;
+ gbcLabel.gridwidth = 1;
+ gbcLabel.gridheight = 1;
+ gbcLabel.insets = new Insets(2, 15, 2, 2);
+ gbcLabel.anchor = GridBagConstraints.LINE_START;
+
+ GridBagConstraints gbcValue = new GridBagConstraints();
+ gbcValue.gridx = 1;
+ gbcValue.gridwidth = 1;
+ gbcValue.gridheight = 1;
+ gbcValue.insets = new Insets(2, 5, 2, 2);
+ gbcValue.anchor = GridBagConstraints.LINE_START;
+
+ // Netscape Certificate Type non-critical extension (if any)
+ // defines the intended uses of the certificate - to make it look like
+ // firefox's view certificate dialog
+ byte[] intendedUses = cert.getExtensionValue("2.16.840.1.113730.1.1"); //Netscape Certificate Type OID/*
+ JLabel jlIntendedUses = null;
+ JTextField jtfIntendedUsesValue = null;
+ JPanel jpUses = null;
+ GridBagConstraints gbc_jpUses = null;
+ if (intendedUses != null)
+ {
+ jlIntendedUses = new JLabel("This certificate has been approved for the following uses:");
+ jlIntendedUses.setFont(new Font(null, Font.BOLD, 11));
+ jlIntendedUses.setBorder(new EmptyBorder(5,5,5,5));
+
+ jtfIntendedUsesValue = new JTextField(45);
+ jtfIntendedUsesValue.setText(getIntendedUses(intendedUses));
+ jtfIntendedUsesValue.setEditable(false);
+ jtfIntendedUsesValue.setFont(new Font(null, Font.PLAIN, 11));
+
+ jpUses = new JPanel(new BorderLayout());
+ jpUses.add(jlIntendedUses, BorderLayout.NORTH);
+ jpUses.add(jtfIntendedUsesValue, BorderLayout.CENTER);
+ JSeparator jsp = new JSeparator(JSeparator.HORIZONTAL);
+ jpUses.add(jsp, BorderLayout.SOUTH);
+
+ gbc_jpUses = (GridBagConstraints) gbcLabel.clone();
+ gbc_jpUses.gridy = 0;
+ gbc_jpUses.gridwidth = 2; //takes two columns
+ gbc_jpUses.insets = new Insets(5, 5, 5, 5);//has slightly bigger insets
+
+ }
+
+ //Issued To
+ JLabel jlIssuedTo = new JLabel("Issued To");
+ jlIssuedTo.setFont(new Font(null, Font.BOLD, 11));
+ GridBagConstraints gbc_jlIssuedTo = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlIssuedTo.gridy = 1;
+ gbc_jlIssuedTo.gridwidth = 2; //takes two columns
+ gbc_jlIssuedTo.insets = new Insets(5, 5, 5, 5);//has slightly bigger insets
+ // Distinguished Name (DN)
+ String sDN = cert.getSubjectX500Principal().getName(X500Principal.RFC2253);
+ CMX509Util util = new CMX509Util();
+ util.parseDN(sDN);
+ // Extract the CN, O, OU and EMAILADDRESS fields
+ String sCN = util.getCN();
+ String sOrg = util.getO();
+ String sOU = util.getOU();
+ //String sEMAILADDRESS = CMX509Util.getEmilAddress();
+ // Common Name (CN)
+ JLabel jlCN = new JLabel("Common Name (CN)");
+ jlCN.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlCN = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlCN.gridy = 2;
+ JLabel jlCNValue = new JLabel(sCN);
+ jlCNValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlCNValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlCNValue.gridy = 2;
+ // Organisation (O)
+ JLabel jlOrg = new JLabel("Organisation (O)");
+ jlOrg.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlOrg = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlOrg.gridy = 3;
+ JLabel jlOrgValue = new JLabel(sOrg);
+ jlOrgValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlOrgValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlOrgValue.gridy = 3;
+ // Organisation Unit (OU)
+ JLabel jlOU = new JLabel("Organisation Unit (OU)");
+ jlOU.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlOU = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlOU.gridy = 4;
+ JLabel jlOUValue = new JLabel(sOU);
+ jlOUValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlOUValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlOUValue.gridy = 4;
+ // E-mail Address
+ //JLabel jlEmail = new JLabel("E-mail Address");
+ //jlEmail.setFont(new Font(null, Font.PLAIN, 11));
+ //GridBagConstraints gbc_jlEmail = (GridBagConstraints) gbcLabel.clone();
+ //gbc_jlEmail.gridy = 5;
+ //JLabel jlEmailValue = new JLabel(sEMAILADDRESS);
+ //jlEmailValue.setFont(new Font(null, Font.PLAIN, 11));
+ //GridBagConstraints gbc_jlEmailValue = (GridBagConstraints) gbcValue.clone();
+ //gbc_jlEmailValue.gridy = 5;
+ // Serial Number
+ JLabel jlSN = new JLabel("Serial Number");
+ jlSN.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlSN = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlSN.gridy = 6;
+ JLabel jlSNValue = new JLabel();
+ // Get the hexadecimal serial number
+ StringBuffer strBuff = new StringBuffer (new BigInteger(1,
+ cert.getSerialNumber().toByteArray()).toString(16).toUpperCase());
+ // Place colons at every two hexadecimal characters
+ if (strBuff.length() > 2) {
+ for (int iCnt = 2; iCnt < strBuff.length(); iCnt += 3) {
+ strBuff.insert(iCnt, ':');
+ }
+ }
+ jlSNValue.setText(strBuff.toString());
+ jlSNValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlSNValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlSNValue.gridy = 6;
+ // Version
+ JLabel jlVersion = new JLabel("Version");
+ jlVersion.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlVersion = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlVersion.gridy = 7;
+ JLabel jlVersionValue = new JLabel(Integer.toString(cert.getVersion()));
+ jlVersionValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlVersionValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlVersionValue.gridy = 7;
+
+ // Issued By
+ JLabel jlIssuedBy = new JLabel("Issued By");
+ jlIssuedBy.setFont(new Font(null, Font.BOLD, 11));
+ GridBagConstraints gbc_jlIssuedBy = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlIssuedBy.gridy = 8;
+ gbc_jlIssuedBy.gridwidth = 2; //takes two columns
+ gbc_jlIssuedBy.insets = new Insets(5, 5, 5, 5);//has slightly bigger insets
+ // Distinguished Name (DN)
+ String iDN = cert.getIssuerX500Principal().getName(X500Principal.RFC2253);
+ util.parseDN(iDN);
+ // Extract the CN, O and OU fields
+ String iCN = util.getCN();
+ String iOrg = util.getO();
+ String iOU = util.getOU();
+ // Common Name (CN)
+ JLabel jlICN = new JLabel("Common Name (CN)");
+ jlICN.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlICN = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlICN.gridy = 9;
+ JLabel jlICNValue = new JLabel(iCN);
+ jlICNValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlICNValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlICNValue.gridy = 9;
+ // Organisation (O)
+ JLabel jlIOrg = new JLabel("Organisation (O)");
+ jlIOrg.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlIOrg = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlIOrg.gridy = 10;
+ JLabel jlIOrgValue = new JLabel(iOrg);
+ jlIOrgValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlIOrgValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlIOrgValue.gridy = 10;
+ // Organisation Unit (OU)
+ JLabel jlIOU = new JLabel("Organisation Unit (OU)");
+ jlIOU.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlIOU = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlIOU.gridy = 11;
+ JLabel jlIOUValue = new JLabel(iOU);
+ jlIOUValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlIOUValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlIOUValue.gridy = 11;
+ // Validity
+ JLabel jlValidity = new JLabel("Validity");
+ jlValidity.setFont(new Font(null, Font.BOLD, 11));
+ GridBagConstraints gbc_jlValidity = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlValidity.gridy = 12;
+ gbc_jlValidity.gridwidth = 2; //takes two columns
+ gbc_jlValidity.insets = new Insets(5, 5, 5, 5);//has slightly bigger insets
+ //Issued On
+ JLabel jlIssuedOn = new JLabel("Issued On");
+ jlIssuedOn.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlIssuedOn = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlIssuedOn.gridy = 13;
+ JLabel jlIssuedOnValue = new JLabel(cert.getNotBefore().toString());
+ jlIssuedOnValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlIssuedOnValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlIssuedOnValue.gridy = 13;
+ // Expires On
+ JLabel jlExpiresOn = new JLabel("Expires On");
+ jlExpiresOn.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlExpiresOn = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlExpiresOn.gridy = 14;
+ JLabel jlExpiresOnValue = new JLabel(cert.getNotAfter().toString());
+ jlExpiresOnValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlExpiresOnValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlExpiresOnValue.gridy = 14;
+
+ // Fingerprints
+ byte[] bCert;
+ try {
+ bCert = cert.getEncoded();
+ }
+ catch (CertificateEncodingException ex) {
+ throw new CMException(
+ "Could not get the encoded form of the certificate.",
+ ex);
+ }
+ JLabel jlFingerprints = new JLabel("Fingerprints");
+ jlFingerprints.setFont(new Font(null, Font.BOLD, 11));
+ GridBagConstraints gbc_jlFingerprints = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlFingerprints.gridy = 15;
+ gbc_jlFingerprints.gridwidth = 2; //takes two columns
+ gbc_jlFingerprints.insets = new Insets(5, 5, 5, 5);//has slightly bigger insets
+ // SHA-1 Fingerprint
+ JLabel jlSHA1Fingerprint = new JLabel("SHA1 Fingerprint");
+ jlSHA1Fingerprint.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlSHA1Fingerprint = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlSHA1Fingerprint.gridy = 16;
+ JLabel jlSHA1FingerprintValue = new JLabel(getMessageDigest(bCert, "SHA1"));
+ jlSHA1FingerprintValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlSHA1FingerprintValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlSHA1FingerprintValue.gridy = 16;
+ // MD5 Fingerprint
+ JLabel jlMD5Fingerprint = new JLabel("MD5 Fingerprint");
+ jlMD5Fingerprint.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlMD5Fingerprint = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlMD5Fingerprint.gridy = 17;
+ JLabel jlMD5FingerprintValue = new JLabel(getMessageDigest(bCert, "MD5"));
+ jlMD5FingerprintValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlMD5FingerprintValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlMD5FingerprintValue.gridy = 17;
+
+ // Empty label to add a bit space at the bottom of the panel
+ // to make it look like firefox's view certificate dialog
+ JLabel jlEmpty = new JLabel("");
+ GridBagConstraints gbc_jlEmpty = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlEmpty.gridy = 18;
+ gbc_jlEmpty.gridwidth = 2; //takes two columns
+ gbc_jlEmpty.ipady = 40;
+
+ JPanel jpCertificate = new JPanel(new GridBagLayout());
+ jpCertificate.setBorder(new CompoundBorder(
+ new EmptyBorder(15, 15, 15, 15), new EtchedBorder()));
+
+ if (intendedUses != null){
+ jpCertificate.add(jpUses, gbc_jpUses);
+ }
+ jpCertificate.add(jlIssuedTo, gbc_jlIssuedTo); // Issued To
+ jpCertificate.add(jlCN, gbc_jlCN);
+ jpCertificate.add(jlCNValue, gbc_jlCNValue);
+ jpCertificate.add(jlOrg, gbc_jlOrg);
+ jpCertificate.add(jlOrgValue, gbc_jlOrgValue);
+ jpCertificate.add(jlOU, gbc_jlOU);
+ jpCertificate.add(jlOUValue, gbc_jlOUValue);
+ //jpCertificate.add(jlEmail, gbc_jlEmail);
+ //jpCertificate.add(jlEmailValue, gbc_jlEmailValue);
+ jpCertificate.add(jlSN, gbc_jlSN);
+ jpCertificate.add(jlSNValue, gbc_jlSNValue);
+ jpCertificate.add(jlVersion, gbc_jlVersion);
+ jpCertificate.add(jlVersionValue, gbc_jlVersionValue);
+ jpCertificate.add(jlIssuedBy, gbc_jlIssuedBy); //Issued By
+ jpCertificate.add(jlICN, gbc_jlICN);
+ jpCertificate.add(jlICNValue, gbc_jlICNValue);
+ jpCertificate.add(jlIOrg, gbc_jlIOrg);
+ jpCertificate.add(jlIOrgValue, gbc_jlIOrgValue);
+ jpCertificate.add(jlIOU, gbc_jlIOU);
+ jpCertificate.add(jlIOUValue, gbc_jlIOUValue);
+ jpCertificate.add(jlValidity, gbc_jlValidity); //Validity
+ jpCertificate.add(jlIssuedOn, gbc_jlIssuedOn);
+ jpCertificate.add(jlIssuedOnValue, gbc_jlIssuedOnValue);
+ jpCertificate.add(jlExpiresOn, gbc_jlExpiresOn);
+ jpCertificate.add(jlExpiresOnValue, gbc_jlExpiresOnValue);
+ jpCertificate.add(jlFingerprints, gbc_jlFingerprints); //Fingerprints
+ jpCertificate.add(jlSHA1Fingerprint, gbc_jlSHA1Fingerprint);
+ jpCertificate.add(jlSHA1FingerprintValue, gbc_jlSHA1FingerprintValue);
+ jpCertificate.add(jlMD5Fingerprint, gbc_jlMD5Fingerprint);
+ jpCertificate.add(jlMD5FingerprintValue, gbc_jlMD5FingerprintValue);
+ jpCertificate.add(jlEmpty, gbc_jlEmpty); //Empty label to get some vertical space on the frame
+
+ // List of AuthN and Dorian URLs
+ JPanel jpAuthNDorianURLs = new JPanel(new BorderLayout());
+ jpAuthNDorianURLs.setBorder(new CompoundBorder(
+ new EmptyBorder(0, 15, 0, 15), new EtchedBorder()));
+ // Label
+ JLabel jlServiceURLs = new JLabel ("The proxy has been obtained using:");
+ jlServiceURLs.setFont(new Font(null, Font.BOLD, 11));
+ jlServiceURLs.setBorder(new EmptyBorder(5,5,5,5));
+
+ JPanel jpURLs = new JPanel();
+ jpURLs.setLayout(new BoxLayout(jpURLs, BoxLayout.Y_AXIS));
+ JLabel jlAuthNServiceURL = new JLabel("Authentication Service");
+ jlAuthNServiceURL.setFont(new Font(null, Font.PLAIN, 11));
+ jlAuthNServiceURL.setAlignmentX(Component.LEFT_ALIGNMENT);
+ jlAuthNServiceURL.setBorder(new EmptyBorder(5,5,0,5));
+
+ JLabel jlDorianServiceURL = new JLabel("Dorian Service");
+ jlDorianServiceURL.setFont(new Font(null, Font.PLAIN, 11));
+ jlDorianServiceURL.setAlignmentX(Component.LEFT_ALIGNMENT);
+ jlDorianServiceURL.setBorder(new EmptyBorder(5,5,0,5));
+
+ JTextField jtfAuthNServiceURL = new JTextField(25);
+ jtfAuthNServiceURL.setEditable(false);
+ jtfAuthNServiceURL.setText(authNServiceURL);
+ jtfAuthNServiceURL.setFont(new Font(null, Font.PLAIN, 11));
+ jtfAuthNServiceURL.setAlignmentX(Component.LEFT_ALIGNMENT);
+
+ JTextField jtfDorianServiceURL = new JTextField(25);
+ jtfDorianServiceURL.setEditable(false);
+ jtfDorianServiceURL.setText(dorianServiceURL);
+ jtfDorianServiceURL.setFont(new Font(null, Font.PLAIN, 11));
+ jtfDorianServiceURL.setAlignmentX(Component.LEFT_ALIGNMENT);
+
+ jpURLs.add(jlAuthNServiceURL);
+ jpURLs.add(jtfAuthNServiceURL);
+ jpURLs.add(jlDorianServiceURL);
+ jpURLs.add(jtfDorianServiceURL);
+
+ jpAuthNDorianURLs.add(jlServiceURLs, BorderLayout.NORTH);
+ jpAuthNDorianURLs.add(jpURLs, BorderLayout.CENTER);
+
+ // OK button
+ JPanel jpOK = new JPanel(new FlowLayout(FlowLayout.CENTER));
+
+ final JButton jbOK = new JButton("OK");
+ jbOK.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent evt)
+ {
+ okPressed();
+ }
+ });
+
+ jpOK.add(jbOK);
+
+ // Put it all together (panel with URL list is already added, if it was not null)
+ getContentPane().add(jpCertificate, BorderLayout.NORTH);
+ getContentPane().add(jpAuthNDorianURLs, BorderLayout.CENTER);
+ getContentPane().add(jpOK, BorderLayout.SOUTH);
+
+ // Resizing wreaks havoc
+ setResizable(false);
+
+ addWindowListener(new WindowAdapter()
+ {
+ public void windowClosing(WindowEvent evt)
+ {
+ closeDialog();
+ }
+ });
+
+ getRootPane().setDefaultButton(jbOK);
+
+ pack();
+
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ jbOK.requestFocus();
+ }
+ });
+ }
+
+ /**
+ * Get the digest of a message as a formatted String.
+ *
+ * @param bMessage The message to digest
+ * @param digestType The message digest algorithm
+ * @return The message digest
+ * @throws CMException If there was a problem generating the message
+ * digest
+ */
+ public static String getMessageDigest(byte[] bMessage,
+ String digestType)
+ throws CMException
+ {
+ // Create message digest object using the supplied algorithm
+ MessageDigest messageDigest;
+ try {
+ messageDigest = MessageDigest.getInstance(digestType);
+ }
+ catch (NoSuchAlgorithmException ex) {
+ throw new CMException("Failed to create message digest.", ex);
+ }
+
+ // Create raw message digest
+ byte[] bFingerPrint = messageDigest.digest(bMessage);
+
+ // Place the raw message digest into a StringBuffer as a Hex number
+ StringBuffer strBuff = new StringBuffer(
+ new BigInteger(1, bFingerPrint).toString(16).toUpperCase());
+
+ // Odd number of characters so add in a padding "0"
+ if ((strBuff.length() % 2) != 0) {
+ strBuff.insert(0, '0');
+ }
+
+ // Place colons at every two hex characters
+ if (strBuff.length() > 2) {
+ for (int iCnt = 2; iCnt < strBuff.length(); iCnt += 3) {
+ strBuff.insert(iCnt, ':');
+ }
+ }
+
+ // Return the formatted message digest
+ return strBuff.toString();
+ }
+
+ /**
+ * Gets the intended certificate uses, i.e. Netscape Certificate Type extension (2.16.840.1.113730.1.1)
+ * value as a string
+ * @param value Extension value as a DER-encoded OCTET string
+ * @return Extension value as a string
+ */
+ private String getIntendedUses(byte[] value)
+ {
+
+ // Netscape Certificate Types (2.16.840.1.113730.1.1)
+ int[] INTENDED_USES = new int[] {
+ NetscapeCertType.sslClient,
+ NetscapeCertType.sslServer,
+ NetscapeCertType.smime,
+ NetscapeCertType.objectSigning,
+ NetscapeCertType.reserved,
+ NetscapeCertType.sslCA,
+ NetscapeCertType.smimeCA,
+ NetscapeCertType.objectSigningCA,
+ };
+
+ // Netscape Certificate Type strings (2.16.840.1.113730.1.1)
+ HashMap<String, String> INTENDED_USES_STRINGS = new HashMap<String, String> ();
+ INTENDED_USES_STRINGS.put("128", "SSL Client");
+ INTENDED_USES_STRINGS.put("64", "SSL Server");
+ INTENDED_USES_STRINGS.put("32", "S/MIME");
+ INTENDED_USES_STRINGS.put("16", "Object Signing");
+ INTENDED_USES_STRINGS.put("8", "Reserved");
+ INTENDED_USES_STRINGS.put("4", "SSL CA");
+ INTENDED_USES_STRINGS.put("2", "S/MIME CA");
+ INTENDED_USES_STRINGS.put("1", "Object Signing CA");
+
+
+ // Get octet string from extension value
+ ASN1OctetString fromByteArray = new DEROctetString(value);
+ byte[] octets = fromByteArray.getOctets();
+ DERBitString fromByteArray2 = new DERBitString(octets);
+ int val = new NetscapeCertType(fromByteArray2).intValue();
+ StringBuffer strBuff = new StringBuffer();
+ for (int i = 0, len = INTENDED_USES.length; i < len; i++) {
+ int use = INTENDED_USES[i];
+ if ((val & use) == use) {
+ strBuff.append(INTENDED_USES_STRINGS.get(String.valueOf(use))+", \n");
+ }
+ }
+ // remove the last ", \n" from the end of the buffer
+ String str = strBuff.toString();
+ str = str.substring(0, str.length()-3);
+ return str;
+ }
+
+ /**
+ * OK button pressed.
+ */
+ private void okPressed()
+ {
+ closeDialog();
+ }
+
+ /**
+ * Closes the View Certificate Entry dialog.
+ */
+ private void closeDialog()
+ {
+ setVisible(false);
+ dispose();
+ }
+}
+
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/ViewCertDetailsDialog.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/ViewCertDetailsDialog.java
new file mode 100644
index 0000000..1f20898
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/ViewCertDetailsDialog.java
@@ -0,0 +1,592 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager;
+
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.Insets;
+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.math.BigInteger;
+import java.util.HashMap;
+
+import javax.swing.DefaultListModel;
+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.JTextField;
+import javax.swing.SwingUtilities;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.EtchedBorder;
+import javax.swing.JSeparator;
+
+import java.util.ArrayList;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import javax.security.auth.x500.X500Principal;
+
+import net.sf.taverna.t2.security.credentialmanager.CMException;
+import net.sf.taverna.t2.security.credentialmanager.CMX509Util;
+
+//import org.apache.log4j.Logger;
+import org.bouncycastle.asn1.ASN1OctetString;
+import org.bouncycastle.asn1.DERBitString;
+import org.bouncycastle.asn1.DEROctetString;
+import org.bouncycastle.asn1.misc.NetscapeCertType;
+
+
+/**
+ * Displays the details of a X.509 certificate.
+ *
+ * @author Alex Nenadic
+ */
+@SuppressWarnings("serial")
+public class ViewCertDetailsDialog
+ extends JDialog
+{
+ // Logger
+ //private static Logger logger = Logger.getLogger(ViewCertDetailsDialog.class);
+
+ // Stores certificate to display
+ private X509Certificate cert;
+
+ // Stores list of serviceURLs to display
+ private ArrayList<String> serviceURLs;
+
+ /**
+ * Creates new ViewCertDetailsDialog dialog where the parent is a frame.
+ */
+ public ViewCertDetailsDialog(JFrame parent, String title, boolean modal,
+ X509Certificate crt, ArrayList<String> serviceURLs)
+ throws CMException
+ {
+ super(parent, title, modal);
+ this.cert = crt;
+ this.serviceURLs = serviceURLs;
+ initComponents();
+ }
+
+ /**
+ * Creates new ViewCertDetailsDialog dialog where the parent is a dialog.
+ */
+ public ViewCertDetailsDialog(JDialog parent, String title, boolean modal,
+ X509Certificate crt, ArrayList<String> urlList)
+ throws CMException
+ {
+ super(parent, title, modal);
+ cert = crt;
+ serviceURLs = urlList;
+ initComponents();
+ }
+
+ /**
+ * Initialise the dialog's GUI components.
+ *
+ * @throws CMException A problem was encountered getting the
+ * certificates' details
+ */
+ private void initComponents()
+ throws CMException
+ {
+
+ // Certificate details:
+
+ // Grid Bag Constraints templates for labels (column 1) and
+ // values (column 2) of certificate details
+ GridBagConstraints gbcLabel = new GridBagConstraints();
+ gbcLabel.gridx = 0;
+ gbcLabel.ipadx = 20;
+ gbcLabel.gridwidth = 1;
+ gbcLabel.gridheight = 1;
+ gbcLabel.insets = new Insets(2, 15, 2, 2);
+ gbcLabel.anchor = GridBagConstraints.LINE_START;
+
+ GridBagConstraints gbcValue = new GridBagConstraints();
+ gbcValue.gridx = 1;
+ gbcValue.gridwidth = 1;
+ gbcValue.gridheight = 1;
+ gbcValue.insets = new Insets(2, 5, 2, 2);
+ gbcValue.anchor = GridBagConstraints.LINE_START;
+
+ // Netscape Certificate Type non-critical extension (if any)
+ // defines the intended uses of the certificate - to make it look like
+ // firefox's view certificate dialog
+ byte[] intendedUses = cert.getExtensionValue("2.16.840.1.113730.1.1"); //Netscape Certificate Type OID/*
+ JLabel jlIntendedUses = null;
+ JTextField jtfIntendedUsesValue = null;
+ JPanel jpUses = null;
+ GridBagConstraints gbc_jpUses = null;
+ if (intendedUses != null)
+ {
+ jlIntendedUses = new JLabel("This certificate has been approved for the following uses:");
+ jlIntendedUses.setFont(new Font(null, Font.BOLD, 11));
+ jlIntendedUses.setBorder(new EmptyBorder(5,5,5,5));
+
+ jtfIntendedUsesValue = new JTextField(45);
+ jtfIntendedUsesValue.setText(getIntendedUses(intendedUses));
+ jtfIntendedUsesValue.setEditable(false);
+ jtfIntendedUsesValue.setFont(new Font(null, Font.PLAIN, 11));
+
+ jpUses = new JPanel(new BorderLayout());
+ jpUses.add(jlIntendedUses, BorderLayout.NORTH);
+ jpUses.add(jtfIntendedUsesValue, BorderLayout.CENTER);
+ JSeparator jsp = new JSeparator(JSeparator.HORIZONTAL);
+ jpUses.add(jsp, BorderLayout.SOUTH);
+
+ gbc_jpUses = (GridBagConstraints) gbcLabel.clone();
+ gbc_jpUses.gridy = 0;
+ gbc_jpUses.gridwidth = 2; //takes two columns
+ gbc_jpUses.insets = new Insets(5, 5, 5, 5);//has slightly bigger insets
+
+ }
+
+ //Issued To
+ JLabel jlIssuedTo = new JLabel("Issued To");
+ jlIssuedTo.setFont(new Font(null, Font.BOLD, 11));
+ GridBagConstraints gbc_jlIssuedTo = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlIssuedTo.gridy = 1;
+ gbc_jlIssuedTo.gridwidth = 2; //takes two columns
+ gbc_jlIssuedTo.insets = new Insets(5, 5, 5, 5);//has slightly bigger insets
+ // Distinguished Name (DN)
+ String sDN = cert.getSubjectX500Principal().getName(X500Principal.RFC2253);
+ CMX509Util util = new CMX509Util();
+ util.parseDN(sDN);
+ // Extract the CN, O, OU and EMAILADDRESS fields
+ String sCN = util.getCN();
+ String sOrg = util.getO();
+ String sOU = util.getOU();
+ //String sEMAILADDRESS = CMX509Util.getEmilAddress();
+ // Common Name (CN)
+ JLabel jlCN = new JLabel("Common Name (CN)");
+ jlCN.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlCN = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlCN.gridy = 2;
+ JLabel jlCNValue = new JLabel(sCN);
+ jlCNValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlCNValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlCNValue.gridy = 2;
+ // Organisation (O)
+ JLabel jlOrg = new JLabel("Organisation (O)");
+ jlOrg.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlOrg = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlOrg.gridy = 3;
+ JLabel jlOrgValue = new JLabel(sOrg);
+ jlOrgValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlOrgValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlOrgValue.gridy = 3;
+ // Organisation Unit (OU)
+ JLabel jlOU = new JLabel("Organisation Unit (OU)");
+ jlOU.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlOU = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlOU.gridy = 4;
+ JLabel jlOUValue = new JLabel(sOU);
+ jlOUValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlOUValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlOUValue.gridy = 4;
+ // E-mail Address
+ //JLabel jlEmail = new JLabel("E-mail Address");
+ //jlEmail.setFont(new Font(null, Font.PLAIN, 11));
+ //GridBagConstraints gbc_jlEmail = (GridBagConstraints) gbcLabel.clone();
+ //gbc_jlEmail.gridy = 5;
+ //JLabel jlEmailValue = new JLabel(sEMAILADDRESS);
+ //jlEmailValue.setFont(new Font(null, Font.PLAIN, 11));
+ //GridBagConstraints gbc_jlEmailValue = (GridBagConstraints) gbcValue.clone();
+ //gbc_jlEmailValue.gridy = 5;
+ // Serial Number
+ JLabel jlSN = new JLabel("Serial Number");
+ jlSN.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlSN = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlSN.gridy = 6;
+ JLabel jlSNValue = new JLabel();
+ // Get the hexadecimal serial number
+ StringBuffer strBuff = new StringBuffer (new BigInteger(1,
+ cert.getSerialNumber().toByteArray()).toString(16).toUpperCase());
+ // Place colons at every two hexadecimal characters
+ if (strBuff.length() > 2) {
+ for (int iCnt = 2; iCnt < strBuff.length(); iCnt += 3) {
+ strBuff.insert(iCnt, ':');
+ }
+ }
+ jlSNValue.setText(strBuff.toString());
+ jlSNValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlSNValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlSNValue.gridy = 6;
+ // Version
+ JLabel jlVersion = new JLabel("Version");
+ jlVersion.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlVersion = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlVersion.gridy = 7;
+ JLabel jlVersionValue = new JLabel(Integer.toString(cert.getVersion()));
+ jlVersionValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlVersionValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlVersionValue.gridy = 7;
+
+ // Issued By
+ JLabel jlIssuedBy = new JLabel("Issued By");
+ jlIssuedBy.setFont(new Font(null, Font.BOLD, 11));
+ GridBagConstraints gbc_jlIssuedBy = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlIssuedBy.gridy = 8;
+ gbc_jlIssuedBy.gridwidth = 2; //takes two columns
+ gbc_jlIssuedBy.insets = new Insets(5, 5, 5, 5);//has slightly bigger insets
+ // Distinguished Name (DN)
+ String iDN = cert.getIssuerX500Principal().getName(X500Principal.RFC2253);
+ util.parseDN(iDN);
+ // Extract the CN, O and OU fields
+ String iCN = util.getCN();
+ String iOrg = util.getO();
+ String iOU = util.getOU();
+ // Common Name (CN)
+ JLabel jlICN = new JLabel("Common Name (CN)");
+ jlICN.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlICN = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlICN.gridy = 9;
+ JLabel jlICNValue = new JLabel(iCN);
+ jlICNValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlICNValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlICNValue.gridy = 9;
+ // Organisation (O)
+ JLabel jlIOrg = new JLabel("Organisation (O)");
+ jlIOrg.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlIOrg = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlIOrg.gridy = 10;
+ JLabel jlIOrgValue = new JLabel(iOrg);
+ jlIOrgValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlIOrgValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlIOrgValue.gridy = 10;
+ // Organisation Unit (OU)
+ JLabel jlIOU = new JLabel("Organisation Unit (OU)");
+ jlIOU.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlIOU = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlIOU.gridy = 11;
+ JLabel jlIOUValue = new JLabel(iOU);
+ jlIOUValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlIOUValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlIOUValue.gridy = 11;
+ // Validity
+ JLabel jlValidity = new JLabel("Validity");
+ jlValidity.setFont(new Font(null, Font.BOLD, 11));
+ GridBagConstraints gbc_jlValidity = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlValidity.gridy = 12;
+ gbc_jlValidity.gridwidth = 2; //takes two columns
+ gbc_jlValidity.insets = new Insets(5, 5, 5, 5);//has slightly bigger insets
+ //Issued On
+ JLabel jlIssuedOn = new JLabel("Issued On");
+ jlIssuedOn.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlIssuedOn = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlIssuedOn.gridy = 13;
+ JLabel jlIssuedOnValue = new JLabel(cert.getNotBefore().toString());
+ jlIssuedOnValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlIssuedOnValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlIssuedOnValue.gridy = 13;
+ // Expires On
+ JLabel jlExpiresOn = new JLabel("Expires On");
+ jlExpiresOn.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlExpiresOn = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlExpiresOn.gridy = 14;
+ JLabel jlExpiresOnValue = new JLabel(cert.getNotAfter().toString());
+ jlExpiresOnValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlExpiresOnValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlExpiresOnValue.gridy = 14;
+
+ // Fingerprints
+ byte[] bCert;
+ try {
+ bCert = cert.getEncoded();
+ }
+ catch (CertificateEncodingException ex) {
+ throw new CMException(
+ "Could not get the encoded form of the certificate.",
+ ex);
+ }
+ JLabel jlFingerprints = new JLabel("Fingerprints");
+ jlFingerprints.setFont(new Font(null, Font.BOLD, 11));
+ GridBagConstraints gbc_jlFingerprints = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlFingerprints.gridy = 15;
+ gbc_jlFingerprints.gridwidth = 2; //takes two columns
+ gbc_jlFingerprints.insets = new Insets(5, 5, 5, 5);//has slightly bigger insets
+ // SHA-1 Fingerprint
+ JLabel jlSHA1Fingerprint = new JLabel("SHA1 Fingerprint");
+ jlSHA1Fingerprint.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlSHA1Fingerprint = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlSHA1Fingerprint.gridy = 16;
+ JLabel jlSHA1FingerprintValue = new JLabel(getMessageDigest(bCert, "SHA1"));
+ jlSHA1FingerprintValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlSHA1FingerprintValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlSHA1FingerprintValue.gridy = 16;
+ // MD5 Fingerprint
+ JLabel jlMD5Fingerprint = new JLabel("MD5 Fingerprint");
+ jlMD5Fingerprint.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlMD5Fingerprint = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlMD5Fingerprint.gridy = 17;
+ JLabel jlMD5FingerprintValue = new JLabel(getMessageDigest(bCert, "MD5"));
+ jlMD5FingerprintValue.setFont(new Font(null, Font.PLAIN, 11));
+ GridBagConstraints gbc_jlMD5FingerprintValue = (GridBagConstraints) gbcValue.clone();
+ gbc_jlMD5FingerprintValue.gridy = 17;
+
+ // Empty label to add a bit space at the bottom of the panel
+ // to make it look like firefox's view certificate dialog
+ JLabel jlEmpty = new JLabel("");
+ GridBagConstraints gbc_jlEmpty = (GridBagConstraints) gbcLabel.clone();
+ gbc_jlEmpty.gridy = 18;
+ gbc_jlEmpty.gridwidth = 2; //takes two columns
+ gbc_jlEmpty.ipady = 40;
+
+ JPanel jpCertificate = new JPanel(new GridBagLayout());
+ jpCertificate.setBorder(new CompoundBorder(
+ new EmptyBorder(15, 15, 15, 15), new EtchedBorder()));
+
+ if (intendedUses != null){
+ jpCertificate.add(jpUses, gbc_jpUses);
+ }
+ jpCertificate.add(jlIssuedTo, gbc_jlIssuedTo); // Issued To
+ jpCertificate.add(jlCN, gbc_jlCN);
+ jpCertificate.add(jlCNValue, gbc_jlCNValue);
+ jpCertificate.add(jlOrg, gbc_jlOrg);
+ jpCertificate.add(jlOrgValue, gbc_jlOrgValue);
+ jpCertificate.add(jlOU, gbc_jlOU);
+ jpCertificate.add(jlOUValue, gbc_jlOUValue);
+ //jpCertificate.add(jlEmail, gbc_jlEmail);
+ //jpCertificate.add(jlEmailValue, gbc_jlEmailValue);
+ jpCertificate.add(jlSN, gbc_jlSN);
+ jpCertificate.add(jlSNValue, gbc_jlSNValue);
+ jpCertificate.add(jlVersion, gbc_jlVersion);
+ jpCertificate.add(jlVersionValue, gbc_jlVersionValue);
+ jpCertificate.add(jlIssuedBy, gbc_jlIssuedBy); //Issued By
+ jpCertificate.add(jlICN, gbc_jlICN);
+ jpCertificate.add(jlICNValue, gbc_jlICNValue);
+ jpCertificate.add(jlIOrg, gbc_jlIOrg);
+ jpCertificate.add(jlIOrgValue, gbc_jlIOrgValue);
+ jpCertificate.add(jlIOU, gbc_jlIOU);
+ jpCertificate.add(jlIOUValue, gbc_jlIOUValue);
+ jpCertificate.add(jlValidity, gbc_jlValidity); //Validity
+ jpCertificate.add(jlIssuedOn, gbc_jlIssuedOn);
+ jpCertificate.add(jlIssuedOnValue, gbc_jlIssuedOnValue);
+ jpCertificate.add(jlExpiresOn, gbc_jlExpiresOn);
+ jpCertificate.add(jlExpiresOnValue, gbc_jlExpiresOnValue);
+ jpCertificate.add(jlFingerprints, gbc_jlFingerprints); //Fingerprints
+ jpCertificate.add(jlSHA1Fingerprint, gbc_jlSHA1Fingerprint);
+ jpCertificate.add(jlSHA1FingerprintValue, gbc_jlSHA1FingerprintValue);
+ jpCertificate.add(jlMD5Fingerprint, gbc_jlMD5Fingerprint);
+ jpCertificate.add(jlMD5FingerprintValue, gbc_jlMD5FingerprintValue);
+ jpCertificate.add(jlEmpty, gbc_jlEmpty); //Empty label to get some vertical space on the frame
+
+ // List of serviceURLs
+ JPanel jpURLs = null; // Panel to hold the URL list
+ if (serviceURLs!=null){ //if service serviceURLs are not null (even if empty - show empty list)
+
+ jpURLs = new JPanel(new BorderLayout());
+ jpURLs.setBorder(new CompoundBorder(
+ new EmptyBorder(0, 15, 0, 15), new EtchedBorder()));
+ // Label
+ JLabel jlServiceURLs = new JLabel ("Service URLs this key pair will be used for:");
+ jlServiceURLs.setFont(new Font(null, Font.BOLD, 11));
+ jlServiceURLs.setBorder(new EmptyBorder(5,5,5,5));
+
+ // New empty service serviceURLs list
+ DefaultListModel jltModel = new DefaultListModel();
+ JList jltServiceURLs = new JList(jltModel);
+ for (String url : serviceURLs){
+ jltModel.addElement(url);
+ }
+ jltServiceURLs.setVisibleRowCount(5); //don't show more than 5 otherwise the window is too big
+
+ // Scroll pane for service serviceURLs
+ JScrollPane jspServiceURLs = new JScrollPane(jltServiceURLs,
+ JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED,
+ JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+ jspServiceURLs.getViewport().setBackground(jltServiceURLs.getBackground());
+
+ jpURLs.add(jlServiceURLs, BorderLayout.NORTH);
+ jpURLs.add(jspServiceURLs, BorderLayout.CENTER);
+
+ // Put it on the main content pane
+ getContentPane().add(jpURLs, BorderLayout.CENTER);
+ }
+
+ // OK button
+ JPanel jpOK = new JPanel(new FlowLayout(FlowLayout.CENTER));
+
+ final JButton jbOK = new JButton("OK");
+ jbOK.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent evt)
+ {
+ okPressed();
+ }
+ });
+
+ jpOK.add(jbOK);
+
+ // Put it all together (panel with URL list is already added, if it was not null)
+ getContentPane().add(jpCertificate, BorderLayout.NORTH);
+ getContentPane().add(jpOK, BorderLayout.SOUTH);
+
+ // Resizing wreaks havoc
+ setResizable(false);
+
+ addWindowListener(new WindowAdapter()
+ {
+ public void windowClosing(WindowEvent evt)
+ {
+ closeDialog();
+ }
+ });
+
+ getRootPane().setDefaultButton(jbOK);
+
+ pack();
+
+ SwingUtilities.invokeLater(new Runnable()
+ {
+ public void run()
+ {
+ jbOK.requestFocus();
+ }
+ });
+ }
+
+ /**
+ * Get the digest of a message as a formatted String.
+ *
+ * @param bMessage The message to digest
+ * @param digestType The message digest algorithm
+ * @return The message digest
+ * @throws CMException If there was a problem generating the message
+ * digest
+ */
+ public static String getMessageDigest(byte[] bMessage,
+ String digestType)
+ throws CMException
+ {
+ // Create message digest object using the supplied algorithm
+ MessageDigest messageDigest;
+ try {
+ messageDigest = MessageDigest.getInstance(digestType);
+ }
+ catch (NoSuchAlgorithmException ex) {
+ throw new CMException("Failed to create message digest.", ex);
+ }
+
+ // Create raw message digest
+ byte[] bFingerPrint = messageDigest.digest(bMessage);
+
+ // Place the raw message digest into a StringBuffer as a Hex number
+ StringBuffer strBuff = new StringBuffer(
+ new BigInteger(1, bFingerPrint).toString(16).toUpperCase());
+
+ // Odd number of characters so add in a padding "0"
+ if ((strBuff.length() % 2) != 0) {
+ strBuff.insert(0, '0');
+ }
+
+ // Place colons at every two hex characters
+ if (strBuff.length() > 2) {
+ for (int iCnt = 2; iCnt < strBuff.length(); iCnt += 3) {
+ strBuff.insert(iCnt, ':');
+ }
+ }
+
+ // Return the formatted message digest
+ return strBuff.toString();
+ }
+
+ /**
+ * Gets the intended certificate uses, i.e. Netscape Certificate Type extension (2.16.840.1.113730.1.1)
+ * value as a string
+ * @param value Extension value as a DER-encoded OCTET string
+ * @return Extension value as a string
+ */
+ private String getIntendedUses(byte[] value)
+ {
+
+ // Netscape Certificate Types (2.16.840.1.113730.1.1)
+ int[] INTENDED_USES = new int[] {
+ NetscapeCertType.sslClient,
+ NetscapeCertType.sslServer,
+ NetscapeCertType.smime,
+ NetscapeCertType.objectSigning,
+ NetscapeCertType.reserved,
+ NetscapeCertType.sslCA,
+ NetscapeCertType.smimeCA,
+ NetscapeCertType.objectSigningCA,
+ };
+
+ // Netscape Certificate Type strings (2.16.840.1.113730.1.1)
+ HashMap<String, String> INTENDED_USES_STRINGS = new HashMap<String, String> ();
+ INTENDED_USES_STRINGS.put("128", "SSL Client");
+ INTENDED_USES_STRINGS.put("64", "SSL Server");
+ INTENDED_USES_STRINGS.put("32", "S/MIME");
+ INTENDED_USES_STRINGS.put("16", "Object Signing");
+ INTENDED_USES_STRINGS.put("8", "Reserved");
+ INTENDED_USES_STRINGS.put("4", "SSL CA");
+ INTENDED_USES_STRINGS.put("2", "S/MIME CA");
+ INTENDED_USES_STRINGS.put("1", "Object Signing CA");
+
+
+ // Get octet string from extension value
+ ASN1OctetString fromByteArray = new DEROctetString(value);
+ byte[] octets = fromByteArray.getOctets();
+ DERBitString fromByteArray2 = new DERBitString(octets);
+ int val = new NetscapeCertType(fromByteArray2).intValue();
+ StringBuffer strBuff = new StringBuffer();
+ for (int i = 0, len = INTENDED_USES.length; i < len; i++) {
+ int use = INTENDED_USES[i];
+ if ((val & use) == use) {
+ strBuff.append(INTENDED_USES_STRINGS.get(String.valueOf(use))+", \n");
+ }
+ }
+ // remove the last ", \n" from the end of the buffer
+ String str = strBuff.toString();
+ str = str.substring(0, str.length()-3);
+ return str;
+ }
+
+ /**
+ * OK button pressed.
+ */
+ private void okPressed()
+ {
+ closeDialog();
+ }
+
+ /**
+ * Closes the View Certificate Entry dialog.
+ */
+ private void closeDialog()
+ {
+ setVisible(false);
+ dispose();
+ }
+}
+
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/ViewPasswordDialog.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/ViewPasswordDialog.java
new file mode 100644
index 0000000..7158486
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/ViewPasswordDialog.java
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager;
+
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+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.JTextField;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.EtchedBorder;
+
+/**
+ * Dialog used for viewing password.
+ *
+ * @author Alexandra Nenadic
+ */
+@SuppressWarnings("serial")
+public class ViewPasswordDialog extends JDialog {
+
+ // Password field
+ private JTextField jtfPassword;
+
+ // Password value
+ private String sPassword;
+
+ /**
+ * Creates new ViewPasswordDialog dialog where the parent is a frame.
+ */
+ public ViewPasswordDialog(JFrame parent, boolean bModal, String password)
+ {
+ this(parent, "View password", bModal, password);
+ }
+
+ /**
+ * Creates new ViewPasswordDialog dialog where the parent is a frame.
+ *
+ * @param parent Parent frame
+ * @param sTitle The dialog's title
+ * @param bModal Is dialog modal?
+ * @param password Password value
+ */
+ public ViewPasswordDialog(JFrame parent, String sTitle, boolean bModal, String password)
+ {
+ super(parent, sTitle, bModal);
+ sPassword = password;
+ initComponents();
+ }
+
+ /**
+ * Creates new ViewPasswordDialog dialog where the parent is a dialog.
+ */
+ public ViewPasswordDialog(JDialog parent, boolean bModal, String password)
+ {
+ this(parent, "View password", bModal, password);
+ }
+
+ /**
+ * Creates new ViewPasswordDialog dialog where the parent is a dialog.
+ */
+ public ViewPasswordDialog(JDialog parent, String sTitle, boolean bModal, String password)
+ {
+ super(parent, sTitle, bModal);
+ sPassword = password;
+ initComponents();
+ }
+
+ /**
+ * Initialise the dialog's GUI components.
+ */
+ private void initComponents()
+ {
+ getContentPane().setLayout(new BorderLayout());
+
+ JLabel jlPassword = new JLabel("Password value");
+
+ //Populate the password field
+ jtfPassword = new JTextField(15);
+ jtfPassword.setText(sPassword);
+ jtfPassword.setEditable(false);
+
+ JButton jbOK = new JButton("OK");
+ jbOK.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent evt)
+ {
+ closeDialog();
+ }
+ });
+
+ JPanel jpPassword = new JPanel(new BorderLayout());
+ jpPassword.add(jlPassword, BorderLayout.NORTH);
+ jpPassword.add(jtfPassword, BorderLayout.CENTER);
+ //jpPassword.setBorder(new EmptyBorder(5, 5, 5, 5));
+ jpPassword.setBorder(new CompoundBorder(
+ new EmptyBorder(5, 5, 5, 5), new EtchedBorder()));
+
+ JPanel jpButtons = new JPanel(new FlowLayout(FlowLayout.CENTER));
+ jpButtons.add(jbOK);
+
+ getContentPane().add(jpPassword, BorderLayout.CENTER);
+ getContentPane().add(jpButtons, BorderLayout.SOUTH);
+
+ addWindowListener(new WindowAdapter()
+ {
+ public void windowClosing(WindowEvent evt)
+ {
+ closeDialog();
+ }
+ });
+
+ setResizable(false);
+
+ getRootPane().setDefaultButton(jbOK);
+
+ pack();
+ }
+
+ /**
+ * Close the dialog.
+ */
+ private void closeDialog()
+ {
+ setVisible(false);
+ dispose();
+ }
+}
+
+
+
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/ViewUsernamePasswordEntryDialog.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/ViewUsernamePasswordEntryDialog.java
new file mode 100644
index 0000000..00e92fe
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/ViewUsernamePasswordEntryDialog.java
@@ -0,0 +1,183 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager;
+
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+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.JButton;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.border.CompoundBorder;
+import javax.swing.border.EmptyBorder;
+import javax.swing.border.EtchedBorder;
+
+/**
+ * Dialog used for viewing service URL, username and password.
+ *
+ * @author Alex Nenadic
+ */
+public class ViewUsernamePasswordEntryDialog
+ extends JDialog
+{
+ private static final long serialVersionUID = -7224904997349644853L;
+
+ // Service URL field
+ private JTextField jtfServiceURL;
+
+ // Username field
+ private JTextField jtfUsername;
+
+ // Password field
+ private JTextField jtfPassword;
+
+ // Service URL value
+ private String serviceURL;
+
+ // Service username value
+ private String username;
+
+ // Service password value
+ private String password;
+
+ /**
+ * Creates new ViewPasswordEntryDialog dialog where the parent is a frame.
+ */
+ public ViewUsernamePasswordEntryDialog(JFrame parent, String currentURL, String currentUsername, String currentPassword)
+ {
+ super(parent, "View username and password for a service", true);
+ serviceURL = currentURL;
+ username = currentUsername;
+ password = currentPassword;
+ initComponents();
+ }
+
+ /**
+ * Creates new ViewPasswordDialog dialog where the parent is a dialog.
+ */
+ public ViewUsernamePasswordEntryDialog(JDialog parent, String currentURL, String currentUsername, String currentPassword)
+ {
+ super(parent, "View username and password for a service", true);
+ serviceURL = currentURL;
+ username = currentUsername;
+ password = currentPassword;
+ initComponents();
+ }
+
+ /**
+ * Initialise the dialog's GUI components.
+ */
+ private void initComponents()
+ {
+ getContentPane().setLayout(new BorderLayout());
+
+ JLabel jlServiceURL = new JLabel("Service URL");
+ jlServiceURL.setBorder(new EmptyBorder(0,5,0,0));
+ JLabel jlUsername = new JLabel("Username");
+ jlUsername.setBorder(new EmptyBorder(0,5,0,0));
+ JLabel jlPassword = new JLabel("Password");
+ jlPassword.setBorder(new EmptyBorder(0,5,0,0));
+
+ //Populate the fields with values and disable user input
+ jtfServiceURL = new JTextField(15);
+ jtfServiceURL.setText(serviceURL);
+ jtfServiceURL.setEditable(false);
+ //jtfServiceURL.setBorder(new EmptyBorder(0,0,0,5));
+
+ jtfUsername = new JTextField(15);
+ jtfUsername.setText(username);
+ jtfUsername.setEditable(false);
+ // jtfUsername.setBorder(new EmptyBorder(0,0,0,5));
+
+ jtfPassword = new JTextField(15);
+ jtfPassword.setText(password);
+ jtfPassword.setEditable(false);
+ //jtfPassword.setBorder(new EmptyBorder(0,0,0,5));
+
+ JButton jbOK = new JButton("OK");
+ jbOK.addActionListener(new ActionListener()
+ {
+ public void actionPerformed(ActionEvent evt)
+ {
+ closeDialog();
+ }
+ });
+
+// JButton jbViewPassword = new JButton("View password");
+// jbViewPassword.addActionListener(new ActionListener()
+// {
+// public void actionPerformed(ActionEvent evt)
+// {
+// showPassword();
+// }
+// });
+
+ JPanel jpPassword = new JPanel(new GridLayout(4, 2, 5, 5));
+ jpPassword.add(jlServiceURL);
+ jpPassword.add(jtfServiceURL);
+ jpPassword.add(jlUsername);
+ jpPassword.add(jtfUsername);
+ jpPassword.add(jlPassword);
+ jpPassword.add(jtfPassword);
+ jpPassword.setBorder(new CompoundBorder(
+ new EmptyBorder(10, 10, 10, 10), new EtchedBorder()));
+
+ JPanel jpButtons = new JPanel(new FlowLayout(FlowLayout.CENTER));
+ jpButtons.add(jbOK);
+ // jpButtons.add(jbViewPassword);
+
+ getContentPane().add(jpPassword, BorderLayout.CENTER);
+ getContentPane().add(jpButtons, BorderLayout.SOUTH);
+
+ addWindowListener(new WindowAdapter()
+ {
+ public void windowClosing(WindowEvent evt)
+ {
+ closeDialog();
+ }
+ });
+
+ setResizable(false);
+
+ getRootPane().setDefaultButton(jbOK);
+
+ pack();
+ }
+
+ /**
+ * Close the dialog.
+ */
+ private void closeDialog()
+ {
+ setVisible(false);
+ dispose();
+ }
+}
+
+
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/action/CredentialManagerAction.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/action/CredentialManagerAction.java
new file mode 100644
index 0000000..b41d512
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/action/CredentialManagerAction.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager.action;
+
+import java.awt.event.ActionEvent;
+
+import javax.swing.AbstractAction;
+import javax.swing.ImageIcon;
+//import javax.swing.SwingUtilities;
+
+import net.sf.taverna.t2.workbench.ui.credentialmanager.CredentialManagerUI;
+
+@SuppressWarnings("serial")
+public class CredentialManagerAction extends AbstractAction {
+
+ private static ImageIcon ICON = new ImageIcon(CredentialManagerAction.class.getResource("/images/cred_manager16x16.png"));
+
+ public CredentialManagerAction() {
+ super("Credential Manager",ICON);
+ }
+
+ public void actionPerformed(ActionEvent e) {
+ CredentialManagerUI cmUI = CredentialManagerUI.getInstance();
+ cmUI.setVisible(true);
+
+// Runnable createAndShowCredentialManagerUI = new Runnable(){
+//
+// public void run()
+// {
+// CredentialManagerUI cmUI = new CredentialManagerUI();
+// cmUI.setVisible(true);
+// }
+// };
+// SwingUtilities.invokeLater(createAndShowCredentialManagerUI);
+
+ }
+}
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/menu/CredentialManagerMenu.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/menu/CredentialManagerMenu.java
new file mode 100644
index 0000000..34a90af
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/menu/CredentialManagerMenu.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager.menu;
+
+import java.net.URI;
+
+import javax.swing.Action;
+
+import org.apache.log4j.Logger;
+
+import net.sf.taverna.t2.security.credentialmanager.CMException;
+import net.sf.taverna.t2.security.credentialmanager.CredentialManager;
+import net.sf.taverna.t2.ui.menu.AbstractMenuAction;
+import net.sf.taverna.t2.workbench.ui.credentialmanager.action.CredentialManagerAction;
+
+public class CredentialManagerMenu extends AbstractMenuAction{
+
+ private static Logger logger = Logger.getLogger(CredentialManagerMenu.class);
+
+ public CredentialManagerMenu() {
+ super(URI.create("http://taverna.sf.net/2008/t2workbench/menu#advanced"),60);
+ // Force initialisation at startup
+
+ try {
+ CredentialManager.initialiseSSL();
+ } catch (CMException e) {
+ logger.error("Could not initialise SSL", e);
+ }
+ }
+
+ @Override
+ protected Action createAction() {
+ return new CredentialManagerAction();
+ }
+
+}
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/toolbar/CredentialManagerToolbarAction.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/toolbar/CredentialManagerToolbarAction.java
new file mode 100644
index 0000000..dd97337
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/toolbar/CredentialManagerToolbarAction.java
@@ -0,0 +1,41 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager.toolbar;
+
+import java.net.URI;
+
+import javax.swing.Action;
+
+import net.sf.taverna.t2.ui.menu.AbstractMenuAction;
+import net.sf.taverna.t2.workbench.ui.credentialmanager.action.CredentialManagerAction;
+
+public class CredentialManagerToolbarAction extends AbstractMenuAction{
+
+ public CredentialManagerToolbarAction() {
+ super(CredentialManagerToolbarSection.CREDENTIAL_MANAGER_TOOLBAR_SECTION,100,URI.create("http://taverna.sf.net/2008/t2workbench/toolbar#credentialManagerAction"));
+ }
+
+ @Override
+ protected Action createAction() {
+ return new CredentialManagerAction();
+ }
+
+}
diff --git a/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/toolbar/CredentialManagerToolbarSection.java b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/toolbar/CredentialManagerToolbarSection.java
new file mode 100644
index 0000000..9b1204f
--- /dev/null
+++ b/src/main/java/net/sf/taverna/t2/workbench/ui/credentialmanager/toolbar/CredentialManagerToolbarSection.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (C) 2007 The University of Manchester
+ *
+ * Modifications to the initial code base are copyright of their
+ * respective authors, or their employers as appropriate.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ ******************************************************************************/
+package net.sf.taverna.t2.workbench.ui.credentialmanager.toolbar;
+
+import java.net.URI;
+
+import net.sf.taverna.t2.ui.menu.AbstractMenuSection;
+import net.sf.taverna.t2.ui.menu.DefaultToolBar;
+
+public class CredentialManagerToolbarSection extends AbstractMenuSection {
+
+ public static URI CREDENTIAL_MANAGER_TOOLBAR_SECTION = URI.create("http://taverna.sf.net/2008/t2workbench/toolbar#credentialManagerSection");
+
+ public CredentialManagerToolbarSection() {
+ super(DefaultToolBar.DEFAULT_TOOL_BAR, 100, CREDENTIAL_MANAGER_TOOLBAR_SECTION);
+ }
+
+}
diff --git a/src/main/resources/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent b/src/main/resources/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent
new file mode 100644
index 0000000..3743c2f
--- /dev/null
+++ b/src/main/resources/META-INF/services/net.sf.taverna.t2.ui.menu.MenuComponent
@@ -0,0 +1,3 @@
+net.sf.taverna.t2.workbench.ui.credentialmanager.menu.CredentialManagerMenu
+#net.sf.taverna.t2.workbench.ui.credentialmanager.toolbar.CredentialManagerToolbarAction
+#net.sf.taverna.t2.workbench.ui.credentialmanager.toolbar.CredentialManagerToolbarSection
\ No newline at end of file
diff --git a/src/main/resources/images/cred_manager.png b/src/main/resources/images/cred_manager.png
new file mode 100644
index 0000000..48cd63c
--- /dev/null
+++ b/src/main/resources/images/cred_manager.png
Binary files differ
diff --git a/src/main/resources/images/cred_manager16x16.png b/src/main/resources/images/cred_manager16x16.png
new file mode 100644
index 0000000..c6e73b5
--- /dev/null
+++ b/src/main/resources/images/cred_manager16x16.png
Binary files differ
diff --git a/src/main/resources/images/cred_manager_transparent.png b/src/main/resources/images/cred_manager_transparent.png
new file mode 100644
index 0000000..1e89bde
--- /dev/null
+++ b/src/main/resources/images/cred_manager_transparent.png
Binary files differ
diff --git a/src/main/resources/images/table/entry_heading.png b/src/main/resources/images/table/entry_heading.png
new file mode 100644
index 0000000..8b59845
--- /dev/null
+++ b/src/main/resources/images/table/entry_heading.png
Binary files differ
diff --git a/src/main/resources/images/table/key_entry.png b/src/main/resources/images/table/key_entry.png
new file mode 100644
index 0000000..1fd18c6
--- /dev/null
+++ b/src/main/resources/images/table/key_entry.png
Binary files differ
diff --git a/src/main/resources/images/table/keypair_entry.png b/src/main/resources/images/table/keypair_entry.png
new file mode 100644
index 0000000..8fd3e8b
--- /dev/null
+++ b/src/main/resources/images/table/keypair_entry.png
Binary files differ
diff --git a/src/main/resources/images/table/trustcert_entry.png b/src/main/resources/images/table/trustcert_entry.png
new file mode 100644
index 0000000..0f110e1
--- /dev/null
+++ b/src/main/resources/images/table/trustcert_entry.png
Binary files differ