http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/CredentialManagerUILauncher.java ---------------------------------------------------------------------- diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/CredentialManagerUILauncher.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/CredentialManagerUILauncher.java new file mode 100644 index 0000000..e500281 --- /dev/null +++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/CredentialManagerUILauncher.java @@ -0,0 +1,95 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.credentialmanager; + +import static java.awt.BorderLayout.CENTER; +import static javax.swing.SwingUtilities.invokeLater; + +import java.awt.Dimension; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.ImageIcon; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; + +/** + * Test launcher for Credential Manager GUI (so it does not have to be + * launched from Taverna). + * + * @author Alexandra Nenadic + */ +public class CredentialManagerUILauncher extends JFrame { + private static final long serialVersionUID = 2079805060170251148L; + + private final ImageIcon launchCMIcon = new ImageIcon( + CredentialManagerUILauncher.class + .getResource("/images/cred_manager.png")); + + public CredentialManagerUILauncher() { + JPanel jpLaunch = new JPanel(); + jpLaunch.setPreferredSize(new Dimension(300, 120)); + + JLabel jlLaunch = new JLabel("T2: Launch Credential Manager GUI"); + + JButton jbLaunch = new JButton(); + jbLaunch.setIcon(launchCMIcon); + jbLaunch.setToolTipText("Launches Credential Manager"); + jbLaunch.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + CredentialManagerUI cmGUI = new CredentialManagerUI(null, null); + if (cmGUI != null) + cmGUI.setVisible(true); + } + }); + + jpLaunch.add(jlLaunch); + jpLaunch.add(jbLaunch); + + getContentPane().add(jpLaunch, CENTER); + + // Handle application close + setDefaultCloseOperation(EXIT_ON_CLOSE); + + pack(); + + // Centre the frame in the centre of the desktop + setLocationRelativeTo(null); + // Set the frame's title + setTitle("Credential Manager GUI Launcher"); + setVisible(true); + } + + /** + * Launcher for the Credential Manager GUI. + */ + public static void main(String[] args) { + // Create and show GUI on the event handler thread + invokeLater(new Runnable(){ + @Override + public void run() { + new CredentialManagerUILauncher(); + } + }); + } +}
http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/CryptoFileFilter.java ---------------------------------------------------------------------- diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/CryptoFileFilter.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/CryptoFileFilter.java new file mode 100644 index 0000000..e26b3f2 --- /dev/null +++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/CryptoFileFilter.java @@ -0,0 +1,72 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.credentialmanager; + +import java.io.File; +import java.util.Arrays; +import java.util.List; + +import javax.swing.filechooser.FileFilter; + +/** + * File filter for filtering against various file extensions. Crypto files + * normally contain a private key (and optionally its certificate chain) or a + * public key certificate (and optionally its certificate chain). + * + * .p12 or .pfx are PKCS #12 keystore files containing private key and its + * public key (+cert chain); .pem are ASN.1 PEM-encoded files containing one (or + * more concatenated) public key certificate(s); .der are ASN.1 DER-encoded + * files containing one public key certificate; .cer are CER-encoded files + * containing one ore more DER-encoded certificates; .crt files are either + * encoded as binary DER or as ASCII PEM. .p7 and .p7c are PKCS #7 certificate + * chain files (i.e. SignedData structure without data, just certificate(s)). + */ +public class CryptoFileFilter extends FileFilter { + // Description of the filter + private String description; + + // Array of file extensions to filter against + private List<String> exts; + + public CryptoFileFilter(String[] extList, String desc) { + exts = Arrays.asList(extList); + this.description = desc; + } + + @Override + public boolean accept(File file) { + if (file.isDirectory()) + return true; + if (file.isFile()) + for (String ext : exts) + if (file.getName().toLowerCase().endsWith(ext)) + return true; + return false; + } + + public void setDescription(String desc) { + this.description = desc; + } + + @Override + public String getDescription() { + return this.description; + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/GetMasterPasswordDialog.java ---------------------------------------------------------------------- diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/GetMasterPasswordDialog.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/GetMasterPasswordDialog.java new file mode 100644 index 0000000..a030c38 --- /dev/null +++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/GetMasterPasswordDialog.java @@ -0,0 +1,168 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.credentialmanager; + +import static java.awt.BorderLayout.CENTER; +import static java.awt.BorderLayout.NORTH; +import static java.awt.BorderLayout.SOUTH; +import static javax.swing.BoxLayout.Y_AXIS; +import static javax.swing.JOptionPane.WARNING_MESSAGE; +import static javax.swing.JOptionPane.showMessageDialog; +import static org.apache.taverna.workbench.ui.credentialmanager.CMStrings.WARN_TITLE; + +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.border.EmptyBorder; + +import org.apache.taverna.workbench.helper.NonBlockedHelpEnabledDialog; + +/** + * Dialog used for getting a master password for Credential Manager from the + * users. + * + * @author Alex Nenadic + */ +@SuppressWarnings("serial") +public class GetMasterPasswordDialog extends NonBlockedHelpEnabledDialog { + /** Password entry field */ + private JPasswordField passwordField; + /** The entered password */ + private String password = null; + /** Text giving user the instructions what to do in the dialog */ + private String instructions; + + public GetMasterPasswordDialog(String instructions) { + super((Frame) null, "Enter master password", true); + this.instructions = instructions; + initComponents(); + } + + private void initComponents() { + getContentPane().setLayout(new BorderLayout()); + + JLabel instructionsLabel = new JLabel(instructions); + // instructionsLabel.setFont(new Font(null, Font.PLAIN, 11)); + + JPanel instructionsPanel = new JPanel(); + instructionsPanel.setLayout(new BoxLayout(instructionsPanel, Y_AXIS)); + instructionsPanel.add(instructionsLabel); + instructionsPanel.setBorder(new EmptyBorder(10, 5, 10, 0)); + + JLabel passwordLabel = new JLabel("Password"); + passwordLabel.setBorder(new EmptyBorder(0, 5, 0, 0)); + + passwordField = new JPasswordField(15); + JPanel passwordPanel = new JPanel(new GridLayout(1, 1, 5, 5)); + passwordPanel.add(passwordLabel); + passwordPanel.add(passwordField); + + JPanel mainPanel = new JPanel(new BorderLayout()); + mainPanel.setBorder(new EmptyBorder(10, 10, 10, 10)); + mainPanel.add(instructionsPanel, NORTH); + mainPanel.add(passwordPanel, CENTER); + + JButton okButton = new JButton("OK"); + okButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + okPressed(); + } + }); + + JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + cancelPressed(); + } + }); + JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); + buttonsPanel.add(okButton); + buttonsPanel.add(cancelButton); + + getContentPane().add(mainPanel, CENTER); + getContentPane().add(buttonsPanel, SOUTH); + + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent evt) { + closeDialog(); + } + }); + + setResizable(false); + getRootPane().setDefaultButton(okButton); + pack(); + } + + /** + * Get the password entered in the dialog. + */ + public String getPassword() { + return password; + } + + /** + * Check that the entered password is not empty and store the entered + * password. + */ + private boolean checkPassword() { + password = new String(passwordField.getPassword()); + + if (password.isEmpty()) { + showMessageDialog(this, "The password cannot be empty", + WARN_TITLE, WARNING_MESSAGE); + return false; + } + + return true; + } + + private void okPressed() { + if (checkPassword()) + closeDialog(); + } + + private void cancelPressed() { + /* + * Set the password to null as it might have changed in the meantime if + * user entered something then cancelled. + */ + password = null; + closeDialog(); + } + + private void closeDialog() { + setVisible(false); + dispose(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/GetPasswordDialog.java ---------------------------------------------------------------------- diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/GetPasswordDialog.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/GetPasswordDialog.java new file mode 100644 index 0000000..d0fa8be --- /dev/null +++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/GetPasswordDialog.java @@ -0,0 +1,167 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.credentialmanager; + +import static java.awt.BorderLayout.CENTER; +import static java.awt.BorderLayout.NORTH; +import static java.awt.BorderLayout.SOUTH; +import static java.awt.Font.PLAIN; +import static javax.swing.JOptionPane.WARNING_MESSAGE; +import static javax.swing.JOptionPane.showMessageDialog; +import static org.apache.taverna.workbench.ui.credentialmanager.CMStrings.WARN_TITLE; + +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.border.EmptyBorder; + +import org.apache.taverna.workbench.helper.NonBlockedHelpEnabledDialog; + +/** + * A general dialog for entering a password. + * + * @author Alex Nenadic + */ +@SuppressWarnings("serial") +public class GetPasswordDialog extends NonBlockedHelpEnabledDialog { + /** Instructions for user explaining the purpose of the password */ + private String instructions = null; + /* Password entry password field */ + private JPasswordField passwordField; + /* Stores the password entered */ + private String password = null; + + public GetPasswordDialog(JFrame parent, String title, boolean modal, + String instr) { + super(parent, title, modal); + instructions = instr; + initComponents(); + } + + public GetPasswordDialog(JDialog parent, String title, boolean modal, + String instr) { + super(parent, title, modal); + instructions = instr; + initComponents(); + } + + private void initComponents() { + getContentPane().setLayout(new BorderLayout()); + + JLabel passwordLabel = new JLabel("Password"); + passwordField = new JPasswordField(15); + + JButton okButton = new JButton("OK"); + okButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + okPressed(); + } + }); + + JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + cancelPressed(); + } + }); + + JLabel instructionsLabel; // Instructions + if (instructions != null) { + instructionsLabel = new JLabel(instructions); + instructionsLabel.setFont(new Font(null, PLAIN, 11)); + instructionsLabel.setBorder(new EmptyBorder(5, 5, 5, 5)); + getContentPane().add(instructionsLabel, NORTH); + } + + JPanel passwordPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); + passwordPanel.add(passwordLabel); + passwordPanel.add(passwordField); + passwordPanel.setBorder(new EmptyBorder(5, 5, 5, 5)); + + JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); + buttonsPanel.add(okButton); + buttonsPanel.add(cancelButton); + + getContentPane().add(passwordPanel, CENTER); + getContentPane().add(buttonsPanel, SOUTH); + + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent evt) { + closeDialog(); + } + }); + + setResizable(false); + getRootPane().setDefaultButton(okButton); + pack(); + } + + /** + * Get the password entered in the dialog. + */ + public String getPassword() { + return password; + } + + /** + * Check that the password entered is not empty and store the entered + * password. + */ + private boolean checkPassword() { + password = new String(passwordField.getPassword()); + + if (password.isEmpty()) { + showMessageDialog(this, "The password cannot be empty", + WARN_TITLE, WARNING_MESSAGE); + return false; + } + + return true; + } + + private void okPressed() { + if (checkPassword()) + closeDialog(); + } + + private void cancelPressed() { + password = null; + closeDialog(); + } + + private void closeDialog() { + setVisible(false); + dispose(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/KeyPairsTableModel.java ---------------------------------------------------------------------- diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/KeyPairsTableModel.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/KeyPairsTableModel.java new file mode 100644 index 0000000..676a45f --- /dev/null +++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/KeyPairsTableModel.java @@ -0,0 +1,212 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.credentialmanager; + +import static javax.swing.JOptionPane.ERROR_MESSAGE; +import static javax.swing.JOptionPane.showMessageDialog; +import static org.apache.taverna.security.credentialmanager.CredentialManager.KeystoreType.KEYSTORE; +import static org.apache.taverna.workbench.ui.credentialmanager.CMStrings.ERROR_TITLE; +import static org.apache.taverna.workbench.ui.credentialmanager.CredentialManagerUI.KEY_PAIR_ENTRY_TYPE; + +import java.util.TreeMap; + +import javax.swing.JFrame; +import javax.swing.table.AbstractTableModel; + +import org.apache.taverna.lang.observer.Observable; +import org.apache.taverna.lang.observer.Observer; +import org.apache.taverna.security.credentialmanager.CMException; +import org.apache.taverna.security.credentialmanager.CredentialManager; +import org.apache.taverna.security.credentialmanager.KeystoreChangedEvent; + +import org.apache.log4j.Logger; + +/** + * The table model used to display the Keystore's key pair entries. + * + * @author Alex Nenadic + */ +@SuppressWarnings("serial") +public class KeyPairsTableModel extends AbstractTableModel implements Observer<KeystoreChangedEvent> { + private static final Logger logger = Logger.getLogger(KeyPairsTableModel.class); + + /** Column names*/ + private String[] columnNames; + /** Table data*/ + private Object[][] data; + private CredentialManager credManager; + + public KeyPairsTableModel(CredentialManager credentialManager) { + credManager = credentialManager; + + if (credManager == null) { + /* Failed to instantiate Credential Manager - warn the user and exit */ + String sMessage = "Failed to instantiate Credential Manager. "; + logger.error("CM GUI: " + sMessage); + showMessageDialog(new JFrame(), sMessage, + ERROR_TITLE, ERROR_MESSAGE); + return; + } + + data = new Object[0][0]; + columnNames = new String[] { + "Entry Type", // type of the Keystore entry + "Owner", // owner's common name + "Issuer", // issuer's common name + "Serial Number", // public key certificate's serial number + "Last Modified", // last modified date of the entry + "URLs", // the invisible column holding the list of URLs associated with this entry + "Alias" // the invisible column holding the actual alias in the Keystore + }; + + try { + load(); + } catch (CMException cme) { + String sMessage = "Failed to load key pairs"; + logger.error(sMessage, cme); + showMessageDialog(new JFrame(), sMessage, + ERROR_TITLE, ERROR_MESSAGE); + return; + } + + // Start observing changes to the Keystore + credManager.addObserver(this); + } + + /** + * Load the table model with the key pair entries from the Keystore. + */ + public void load() throws CMException { + // Place key pair entries' aliases in a tree map to sort them + TreeMap<String, String> sortedAliases = new TreeMap<>(); + + for (String alias: credManager.getAliases(KEYSTORE)) + /* + * We are only interested in key pair entries here. + * + * Alias for such entries is constructed as + * "keypair#<CERT_SERIAL_NUMBER>#<CERT_COMMON_NAME>" where + */ + if (alias.startsWith("keypair#")) + sortedAliases.put(alias, alias); + + // Create one table row for each key pair entry + data = new Object[sortedAliases.size()][7]; + + /* + * Iterate through the sorted aliases (if any), retrieving the key pair + * entries and populating the table model + */ + int iCnt = 0; + for (String alias : sortedAliases.values()) { + /* + * Populate the type column - it is set with an integer but a custom + * cell renderer will cause a suitable icon to be displayed + */ + data[iCnt][0] = KEY_PAIR_ENTRY_TYPE; + + /* + * Split the alias string to extract owner, issuer and serial number + * alias = + * "keypair#"<SUBJECT_COMMON_NAME>"#"<ISSUER_COMMON_NAME>"#"<SERIAL_NUMBER> + */ + String[] aliasComponents = alias.split("#"); + + // Populate the owner column extracted from the alias + data[iCnt][1] = aliasComponents[1]; + + // Populate the issuer column extracted from the alias + data[iCnt][2] = aliasComponents[2]; + + // Populate the serial number column extracted from the alias + data[iCnt][3] = aliasComponents[3]; + + // Populate the modified date column ("UBER" keystore type supports creation date) + //data[iCnt][4] = credManager.getEntryCreationDate(CredentialManager.KEYSTORE, alias); + + // Populate the invisible URLs list column + //data[iCnt][5] = credManager.getServiceURLsForKeyPair(alias); + + // Populate the invisible alias column + data[iCnt][6] = alias; + + iCnt++; + } + + fireTableDataChanged(); + } + + /** + * Get the number of columns in the table. + */ + @Override + public int getColumnCount() { + return columnNames.length; + } + + /** + * Get the number of rows in the table. + */ + @Override + public int getRowCount() { + return data.length; + } + + /** + * Get the name of the column at the given position. + */ + @Override + public String getColumnName(int iCol) { + return columnNames[iCol]; + } + + /** + * Get the cell value at the given row and column position. + */ + @Override + public Object getValueAt(int iRow, int iCol) { + return data[iRow][iCol]; + } + + /** + * Get the class at of the cells at the given column position. + */ + @Override + public Class<? extends Object> getColumnClass(int iCol) { + return getValueAt(0, iCol).getClass(); + } + + /** + * Is the cell at the given row and column position editable? + */ + @Override + public boolean isCellEditable(int iRow, int iCol) { + // The table is always read-only + return false; + } + + @Override + public void notify(Observable<KeystoreChangedEvent> sender, + KeystoreChangedEvent message) throws Exception { + // reload the table + if (message.keystoreType.equals(KEYSTORE)) + load(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewEditPasswordEntryDialog.java ---------------------------------------------------------------------- diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewEditPasswordEntryDialog.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewEditPasswordEntryDialog.java new file mode 100644 index 0000000..829144a --- /dev/null +++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewEditPasswordEntryDialog.java @@ -0,0 +1,396 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.credentialmanager; + +import static java.awt.BorderLayout.CENTER; +import static java.awt.BorderLayout.SOUTH; +import static java.awt.GridBagConstraints.HORIZONTAL; +import static java.awt.GridBagConstraints.NONE; +import static java.awt.GridBagConstraints.WEST; +import static javax.swing.JOptionPane.ERROR_MESSAGE; +import static javax.swing.JOptionPane.WARNING_MESSAGE; +import static javax.swing.JOptionPane.showMessageDialog; +import static org.apache.taverna.workbench.ui.credentialmanager.CMStrings.ALERT_TITLE; +import static org.apache.taverna.workbench.ui.credentialmanager.CMStrings.ERROR_TITLE; +import static org.apache.taverna.workbench.ui.credentialmanager.CMStrings.WARN_TITLE; + +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.Insets; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.List; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPasswordField; +import javax.swing.JTextField; +import javax.swing.JPanel; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; +import javax.swing.border.EtchedBorder; + +import org.apache.log4j.Logger; + +import org.apache.taverna.security.credentialmanager.CMException; +import org.apache.taverna.security.credentialmanager.CredentialManager; +import org.apache.taverna.workbench.helper.NonBlockedHelpEnabledDialog; + +/** + * Dialog used for editing or entering new service URI, username or password for + * a password entry. + * + * @author Alex Nenadic + */ +@SuppressWarnings("serial") +public class NewEditPasswordEntryDialog extends NonBlockedHelpEnabledDialog +{ + private static final Logger logger = Logger + .getLogger(NewEditPasswordEntryDialog.class); + /** 'Edit' mode constant - the dialog is in the 'edit' entry mode */ + private static final String EDIT_MODE = "EDIT"; + /** 'New' mode constant - the dialog is in the 'new' entry mode */ + private static final String NEW_MODE = "NEW"; + + /** + * Mode of this dialog - {@link #NEW_MODE} for entering new password entry + * and {@link #EDIT_MODE} for editting an existing password entry + */ + String mode; + /** Service URI field */ + private JTextField serviceURIField; + /** Username field */ + private JTextField usernameField; + /** First password entry field */ + private JPasswordField passwordField; + /** Password confirmation entry field */ + private JPasswordField passwordConfirmField; + /** Stores service URI entered */ + private URI serviceURI; + /** Stores previous service URI for {@link #EDIT_MODE} */ + private URI serviceURIOld; + /** Stores username entered */ + private String username; + /** Stores password entered*/ + private String password; + private CredentialManager credentialManager; + + public NewEditPasswordEntryDialog(JFrame parent, String title, + boolean modal, URI currentURI, String currentUsername, + String currentPassword, CredentialManager credentialManager) { + super(parent, title, modal); + serviceURI = currentURI; + username = currentUsername; + password = currentPassword; + this.credentialManager = credentialManager; + if (serviceURI == null && username == null && password == null) { + // if passed values are all null + mode = NEW_MODE; // dialog is for entering a new password entry + } else { + mode = EDIT_MODE; // dialog is for editing an existing entry + serviceURIOld = currentURI; + } + initComponents(); + } + + public NewEditPasswordEntryDialog(JDialog parent, String title, + boolean modal, URI currentURI, String currentUsername, + String currentPassword, CredentialManager credentialManager) { + super(parent, title, modal); + serviceURI = currentURI; + username = currentUsername; + password = currentPassword; + this.credentialManager = credentialManager; + if (serviceURI == null && username == null && password == null) { + // if passed values are all null + mode = NEW_MODE; // dialog is for entering new password entry + } else { + mode = EDIT_MODE; // dialog is for editing existing entry + serviceURIOld = currentURI; + } + initComponents(); + } + + private void initComponents() { + getContentPane().setLayout(new BorderLayout()); + + JLabel serviceURILabel = new JLabel("Service URI"); + serviceURILabel.setBorder(new EmptyBorder(0,5,0,0)); + + JLabel usernameLabel = new JLabel("Username"); + usernameLabel.setBorder(new EmptyBorder(0,5,0,0)); + + JLabel passwordLabel = new JLabel("Password"); + passwordLabel.setBorder(new EmptyBorder(0,5,0,0)); + + JLabel passwordConfirmLabel = new JLabel("Confirm password"); + passwordConfirmLabel.setBorder(new EmptyBorder(0,5,0,0)); + + serviceURIField = new JTextField(); + //jtfServiceURI.setBorder(new EmptyBorder(0,0,0,5)); + + usernameField = new JTextField(15); + //jtfUsername.setBorder(new EmptyBorder(0,0,0,5)); + + passwordField = new JPasswordField(15); + //jpfFirstPassword.setBorder(new EmptyBorder(0,0,0,5)); + + passwordConfirmField = new JPasswordField(15); + //jpfConfirmPassword.setBorder(new EmptyBorder(0,0,0,5)); + + //If in EDIT_MODE - populate the fields with current values + if (mode.equals(EDIT_MODE)) { + serviceURIField.setText(serviceURI.toASCIIString()); + usernameField.setText(username); + passwordField.setText(password); + passwordConfirmField.setText(password); + } + + JButton okButton = new JButton("OK"); + okButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + okPressed(); + } + }); + + JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + cancelPressed(); + } + }); + + JPanel passwordPanel = new JPanel(new GridBagLayout()); + + GridBagConstraints gbc = new GridBagConstraints(); + gbc.weighty = 0.0; + + gbc.weightx = 0.0; + gbc.gridx = 0; + gbc.gridy = 0; + gbc.fill = NONE; + gbc.anchor = WEST; + gbc.insets = new Insets(5, 10, 0, 0); + passwordPanel.add(serviceURILabel, gbc); + + gbc.weightx = 1.0; + gbc.gridx = 1; + gbc.gridy = 0; + gbc.fill = HORIZONTAL; + gbc.anchor = WEST; + gbc.insets = new Insets(5, 10, 0, 5); + passwordPanel.add(serviceURIField, gbc); + + gbc.weightx = 0.0; + gbc.gridx = 0; + gbc.gridy = 1; + gbc.fill = NONE; + gbc.anchor = WEST; + gbc.insets = new Insets(5, 10, 0, 0); + passwordPanel.add(usernameLabel, gbc); + + gbc.weightx = 1.0; + gbc.gridx = 1; + gbc.gridy = 1; + gbc.fill = HORIZONTAL; + gbc.anchor = WEST; + gbc.insets = new Insets(5, 10, 0, 5); + passwordPanel.add(usernameField, gbc); + + gbc.weightx = 0.0; + gbc.gridx = 0; + gbc.gridy = 2; + gbc.fill = NONE; + gbc.anchor = WEST; + gbc.insets = new Insets(5, 10, 0, 0); + passwordPanel.add(passwordLabel, gbc); + + gbc.weightx = 1.0; + gbc.gridx = 1; + gbc.gridy = 2; + gbc.fill = HORIZONTAL; + gbc.anchor = WEST; + gbc.insets = new Insets(5, 10, 0, 5); + passwordPanel.add(passwordField, gbc); + + gbc.weightx = 0.0; + gbc.gridx = 0; + gbc.gridy = 3; + gbc.fill = NONE; + gbc.anchor = WEST; + gbc.insets = new Insets(5, 10, 0, 0); + passwordPanel.add(passwordConfirmLabel, gbc); + + gbc.weightx = 1.0; + gbc.gridx = 1; + gbc.gridy = 3; + gbc.fill = HORIZONTAL; + gbc.anchor = WEST; + gbc.insets = new Insets(5, 10, 0, 5); + passwordPanel.add(passwordConfirmField, gbc); + + passwordPanel.setBorder(new CompoundBorder(new EmptyBorder(10, 10, 10, + 10), new EtchedBorder())); + + JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); + buttonsPanel.add(okButton); + buttonsPanel.add(cancelButton); + + getContentPane().add(passwordPanel, CENTER); + getContentPane().add(buttonsPanel, SOUTH); + + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent evt) { + closeDialog(); + } + }); + + //setResizable(false); + getRootPane().setDefaultButton(okButton); + pack(); + } + + /** + * Get the username entered in the dialog. + */ + public String getUsername() { + return username; + } + + /** + * Get the service URI entered in the dialog. + */ + public URI getServiceURI() { + return serviceURI; + } + + /** + * Get the password entered in the dialog. + */ + public String getPassword() { + return password; + } + + /** + * Checks that the user has entered a non-empty service URI, a non-empty + * username, a non-empty password and that an entry with the same URI + * already does not already exist in the Keystore. Store the new password. + */ + private boolean checkControls() { + String serviceURIString = new String(serviceURIField.getText()); + if (serviceURIString.isEmpty()) { + showMessageDialog(this, "Service URI cannot be empty", + WARN_TITLE, WARNING_MESSAGE); + return false; + } + try { + serviceURI = new URI(serviceURIString); + } catch (URISyntaxException e) { + showMessageDialog(this, "Service URI is not a valid URI", + WARN_TITLE, WARNING_MESSAGE); + return false; + } + + username = new String(usernameField.getText()); + if (username.isEmpty()) { + showMessageDialog(this, "Username cannot be empty", WARN_TITLE, + WARNING_MESSAGE); + return false; + } + + String firstPassword = new String(passwordField.getPassword()); + String confirmPassword = new String(passwordConfirmField.getPassword()); + + if (!firstPassword.equals(confirmPassword)) { + // passwords do not match + showMessageDialog(this, "Passwords do not match", WARN_TITLE, + WARNING_MESSAGE); + return false; + } + if (firstPassword.isEmpty()) { + // passwords match but are empty + showMessageDialog(this, "Password cannot be empty", WARN_TITLE, + WARNING_MESSAGE); + return false; + } + + // passwords the same and non-empty + password = firstPassword; + + // Check if the entered service URL is already associated with another password entry in the Keystore + List<URI> uriList = null; + try { + uriList = credentialManager.getServiceURIsForAllUsernameAndPasswordPairs(); + } catch (CMException cme) { + // Failed to instantiate Credential Manager - warn the user and exit + String exMessage = "Failed to instantiate Credential Manager to check for duplicate service URIs."; + logger.error(exMessage, cme); + showMessageDialog(new JFrame(), exMessage, ERROR_TITLE, + ERROR_MESSAGE); + return false; + } + + if (uriList != null) { // should not be null really (although can be empty). Check anyway. + if (mode.equals(EDIT_MODE)) // edit mode + // Remove the current entry's service URI from the list + uriList.remove(serviceURIOld); + + if (uriList.contains(serviceURI)) { // found another entry for this service URI + // Warn the user and exit + showMessageDialog( + this, + "The entered service URI is already associated with another password entry", + ALERT_TITLE, WARNING_MESSAGE); + return false; + } + } + + return true; + } + + private void okPressed() { + if (checkControls()) + closeDialog(); + } + + private void cancelPressed() { + // Set all fields to null to indicate that cancel button was pressed + serviceURI = null; + username = null; + password = null; + closeDialog(); + } + + private void closeDialog() { + setVisible(false); + dispose(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewKeyPairEntryDialog.java ---------------------------------------------------------------------- diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewKeyPairEntryDialog.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewKeyPairEntryDialog.java new file mode 100644 index 0000000..b2cefa8 --- /dev/null +++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewKeyPairEntryDialog.java @@ -0,0 +1,303 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.credentialmanager; + +import static java.awt.BorderLayout.CENTER; +import static java.awt.BorderLayout.SOUTH; +import static java.awt.BorderLayout.WEST; +import static java.awt.Font.PLAIN; +import static javax.swing.BoxLayout.Y_AXIS; +import static javax.swing.JOptionPane.ERROR_MESSAGE; +import static javax.swing.JOptionPane.WARNING_MESSAGE; +import static javax.swing.JOptionPane.showMessageDialog; +import static javax.swing.ListSelectionModel.SINGLE_SELECTION; +import static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED; +import static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED; +import static org.apache.taverna.workbench.ui.credentialmanager.CMStrings.ALERT_TITLE; +import static org.apache.taverna.workbench.ui.credentialmanager.CMStrings.ERROR_TITLE; + +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.security.GeneralSecurityException; +import java.security.Key; +import java.security.KeyStore; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.border.EmptyBorder; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +import org.apache.taverna.security.credentialmanager.CMException; +import org.apache.taverna.security.credentialmanager.DistinguishedNameParser; +import org.apache.taverna.workbench.helper.NonBlockedHelpEnabledDialog; + +/** + * Allows the user import a key pair from a PKCS #12 file (keystore). + */ +@SuppressWarnings("serial") +class NewKeyPairEntryDialog extends NonBlockedHelpEnabledDialog { + //private static final Logger logger = Logger.getLogger(NewKeyPairEntryDialog.class); + + /** List of key pairs available for import */ + private JList<String> keyPairsJList; + /** PKCS #12 keystore */ + private KeyStore pkcs12KeyStore; + /** Private key part of the key pair chosen by the user for import */ + private Key privateKey; + /** Certificate chain part of the key pair chosen by the user for import */ + private Certificate[] certificateChain; + /** Key pair alias to be used for this entry in the Keystore */ + private String alias; + private final DistinguishedNameParser dnParser; + + public NewKeyPairEntryDialog(JFrame parent, String title, boolean modal, + KeyStore pkcs12KeyStore, DistinguishedNameParser dnParser) + throws CMException { + super(parent, title, modal); + this.pkcs12KeyStore = pkcs12KeyStore; + this.dnParser = dnParser; + initComponents(); + } + + public NewKeyPairEntryDialog(JDialog parent, String title, boolean modal, + KeyStore pkcs12KeyStore, DistinguishedNameParser dnParser) + throws CMException { + super(parent, title, modal); + this.pkcs12KeyStore = pkcs12KeyStore; + this.dnParser = dnParser; + initComponents(); + } + + /** + * Get the private part of the key pair. + */ + public Key getPrivateKey() { + return privateKey; + } + + /** + * Get the certificate chain part of the key pair. + */ + public Certificate[] getCertificateChain() { + return certificateChain; + } + + /** + * Get the keystore alias of the key pair. + */ + public String getAlias() { + return alias; + } + + private void initComponents() throws CMException { + // Instructions + JLabel instructionsLabel = new JLabel("Select a key pair to import:"); + instructionsLabel.setFont(new Font(null, PLAIN, 11)); + instructionsLabel.setBorder(new EmptyBorder(5, 5, 5, 5)); + JPanel instructionsPanel = new JPanel(new BorderLayout()); + instructionsPanel.add(instructionsLabel, WEST); + + // Import button + final JButton importButton = new JButton("Import"); + importButton.setEnabled(false); + importButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + importPressed(); + } + }); + + // Certificate details button + final JButton certificateDetailsButton = new JButton("Details"); + certificateDetailsButton.setEnabled(false); + certificateDetailsButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + certificateDetailsPressed(); + } + }); + + // List to hold keystore's key pairs + keyPairsJList = new JList<>(); + keyPairsJList.setSelectionMode(SINGLE_SELECTION); + keyPairsJList.addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent evt) { + boolean enabled = keyPairsJList.getSelectedIndex() >= 0; + importButton.setEnabled(enabled); + certificateDetailsButton.setEnabled(enabled); + } + }); + + // Put the key list into a scroll pane + JScrollPane keyPairsScrollPane = new JScrollPane(keyPairsJList, + VERTICAL_SCROLLBAR_AS_NEEDED, HORIZONTAL_SCROLLBAR_AS_NEEDED); + keyPairsScrollPane.getViewport().setBackground( + keyPairsJList.getBackground()); + + JPanel keyPairsPanel = new JPanel(); + keyPairsPanel.setLayout(new BoxLayout(keyPairsPanel, Y_AXIS)); + keyPairsPanel.setBorder(new EmptyBorder(10, 10, 10, 10)); + + instructionsPanel.setAlignmentY(LEFT_ALIGNMENT); + keyPairsPanel.add(instructionsPanel); + keyPairsScrollPane.setAlignmentY(LEFT_ALIGNMENT); + keyPairsPanel.add(keyPairsScrollPane); + + // Cancel button + final JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + cancelPressed(); + } + }); + + JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); + buttonsPanel.add(certificateDetailsButton); + buttonsPanel.add(importButton); + buttonsPanel.add(cancelButton); + + getContentPane().setLayout(new BorderLayout()); + getContentPane().add(keyPairsPanel, CENTER); + getContentPane().add(buttonsPanel, SOUTH); + + // Populate the list + populateKeyPairList(); + + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent evt) { + closeDialog(); + } + }); + + setResizable(false); + getRootPane().setDefaultButton(importButton); + pack(); + } + + /** + * Populate the key pair list with the PKCS #12 keystore's key pair aliases. + */ + private void populateKeyPairList() throws CMException { + try { + List<String> keyPairAliases = new ArrayList<>(); + + Enumeration<String> aliases = pkcs12KeyStore.aliases(); + while (aliases.hasMoreElements()) { + String alias = aliases.nextElement(); + + if (pkcs12KeyStore.isKeyEntry(alias)) { + pkcs12KeyStore.getKey(alias, new char[] {}); + Certificate[] certs = pkcs12KeyStore + .getCertificateChain(alias); + if (certs != null && certs.length != 0) + keyPairAliases.add(alias); + } + } + + if (!keyPairAliases.isEmpty()) { + keyPairsJList.setListData(keyPairAliases.toArray(new String[0])); + keyPairsJList.setSelectedIndex(0); + } else + // No key pairs were found - warn the user + showMessageDialog(this, + "No private key pairs were found in the file", + ALERT_TITLE, WARNING_MESSAGE); + } catch (GeneralSecurityException ex) { + throw new CMException("Problem occured while reading the PKCS #12 file.", + ex); + } + } + + /** + * Display the selected key pair's certificate. + */ + private void certificateDetailsPressed() { + try { + String alias = (String) keyPairsJList.getSelectedValue(); + + // Convert the certificate object into an X509Certificate object. + X509Certificate cert = dnParser.convertCertificate(pkcs12KeyStore + .getCertificate(alias)); + + ViewCertDetailsDialog viewCertificateDialog = new ViewCertDetailsDialog( + this, "Certificate details", true, (X509Certificate) cert, + null, dnParser); + viewCertificateDialog.setLocationRelativeTo(this); + viewCertificateDialog.setVisible(true); + } catch (Exception ex) { + showMessageDialog(this, + "Failed to obtain certificate details to show", + ALERT_TITLE, WARNING_MESSAGE); + closeDialog(); + } + } + + public void importPressed() { + String alias = (String) keyPairsJList.getSelectedValue(); + try { + privateKey = pkcs12KeyStore.getKey(alias, new char[] {}); + certificateChain = pkcs12KeyStore.getCertificateChain(alias); + this.alias = alias; + } catch (Exception ex) { + showMessageDialog( + this, + "Failed to load the private key and certificate chain from the PKCS #12 file.", + ERROR_TITLE, ERROR_MESSAGE); + } + + closeDialog(); + } + + public void cancelPressed() { + /* + * Set everything to null, just in case some of the values have been set + * previously and the user pressed 'cancel' after that. + */ + privateKey = null; + certificateChain = null; + closeDialog(); + } + + private void closeDialog() { + setVisible(false); + dispose(); + } + +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewTrustCertsDialog.java ---------------------------------------------------------------------- diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewTrustCertsDialog.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewTrustCertsDialog.java new file mode 100644 index 0000000..dc342a1 --- /dev/null +++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/NewTrustCertsDialog.java @@ -0,0 +1,247 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.credentialmanager; + +import static java.awt.BorderLayout.CENTER; +import static java.awt.BorderLayout.SOUTH; +import static java.awt.BorderLayout.WEST; +import static java.awt.Font.PLAIN; +import static javax.security.auth.x500.X500Principal.RFC2253; +import static javax.swing.BoxLayout.Y_AXIS; +import static javax.swing.JOptionPane.WARNING_MESSAGE; +import static javax.swing.JOptionPane.showMessageDialog; +import static javax.swing.ListSelectionModel.MULTIPLE_INTERVAL_SELECTION; +import static javax.swing.ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED; +import static javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED; +import static org.apache.taverna.workbench.ui.credentialmanager.CMStrings.ALERT_TITLE; + +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.security.cert.X509Certificate; +import java.util.ArrayList; + +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; +import javax.swing.border.EtchedBorder; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; + +import org.apache.taverna.security.credentialmanager.DistinguishedNameParser; +import org.apache.taverna.security.credentialmanager.ParsedDistinguishedName; +import org.apache.taverna.workbench.helper.NonBlockedHelpEnabledDialog; + +/** + * Allows the user to import one or more trusted certificates from a file. + */ +@SuppressWarnings("serial") +public class NewTrustCertsDialog extends NonBlockedHelpEnabledDialog { + private JList<String> trustedCertsJList; + /** List of trusted certs read from the file and available for import */ + private ArrayList<X509Certificate> availableTrustedCerts = new ArrayList<>(); + /** List of trusted certs selected for import */ + private ArrayList<X509Certificate> selectedTrustedCerts; + private final DistinguishedNameParser dnParser; + + public NewTrustCertsDialog(JFrame parent, String title, boolean modal, + ArrayList<X509Certificate> lCerts, DistinguishedNameParser dnParser) { + super(parent, title, modal); + availableTrustedCerts = lCerts; + this.dnParser = dnParser; + initComponents(); + } + + public NewTrustCertsDialog(JDialog parent, String title, boolean modal, + ArrayList<X509Certificate> lCerts, DistinguishedNameParser dnParser) { + super(parent, title, modal); + availableTrustedCerts = lCerts; + this.dnParser = dnParser; + initComponents(); + } + + private void initComponents() { + // Instructions + JLabel instructionsLabel = new JLabel( + "Select one or more certificates for import:"); + instructionsLabel.setFont(new Font(null, PLAIN, 11)); + instructionsLabel.setBorder(new EmptyBorder(5, 5, 5, 5)); + JPanel instructionsPanel = new JPanel(new BorderLayout()); + instructionsPanel.add(instructionsLabel, WEST); + + // Import button + final JButton importButton = new JButton("Import"); + importButton.setEnabled(false); + importButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + importPressed(); + } + }); + + // Certificate details button + final JButton certificateDetailsButton = new JButton( + "Certificate Details"); + certificateDetailsButton.setEnabled(false); + certificateDetailsButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + certificateDetailsPressed(); + } + }); + + // List with trusted certs' aliases + trustedCertsJList = new JList<>(); + trustedCertsJList.setSelectionMode(MULTIPLE_INTERVAL_SELECTION); + trustedCertsJList.addListSelectionListener(new ListSelectionListener() { + @Override + public void valueChanged(ListSelectionEvent evt) { + boolean enabled = trustedCertsJList.getSelectedIndex() >= 0; + importButton.setEnabled(enabled); + certificateDetailsButton.setEnabled(enabled); + } + }); + // Populate the list - get the certificate subjects' CNs + ArrayList<String> cns = new ArrayList<>(); + for (int i = 0; i < availableTrustedCerts.size(); i++) { + String subjectDN = ((X509Certificate) availableTrustedCerts.get(i)) + .getSubjectX500Principal().getName(RFC2253); + ParsedDistinguishedName parsedDN = dnParser.parseDN(subjectDN); + String subjectCN = parsedDN.getCN(); + cns.add(i, subjectCN); + } + trustedCertsJList.setListData(cns.toArray(new String[0])); + trustedCertsJList.setSelectedIndex(0); + + // Put the list into a scroll pane + JScrollPane trustedCertsScrollPanel = new JScrollPane( + trustedCertsJList, VERTICAL_SCROLLBAR_AS_NEEDED, + HORIZONTAL_SCROLLBAR_AS_NEEDED); + trustedCertsScrollPanel.getViewport().setBackground( + trustedCertsJList.getBackground()); + + JPanel trustedCertsPanel = new JPanel(); + trustedCertsPanel.setLayout(new BoxLayout(trustedCertsPanel, Y_AXIS)); + trustedCertsPanel.setBorder(new CompoundBorder(new CompoundBorder( + new EmptyBorder(5, 5, 5, 5), new EtchedBorder()), + new EmptyBorder(5, 5, 5, 5))); + + instructionsPanel.setAlignmentY(LEFT_ALIGNMENT); + trustedCertsPanel.add(instructionsPanel); + trustedCertsScrollPanel.setAlignmentY(LEFT_ALIGNMENT); + trustedCertsPanel.add(trustedCertsScrollPanel); + certificateDetailsButton.setAlignmentY(RIGHT_ALIGNMENT); + trustedCertsPanel.add(certificateDetailsButton); + + // Cancel button + final JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + cancelPressed(); + } + }); + + JPanel jpButtons = new JPanel(new FlowLayout(FlowLayout.CENTER)); + jpButtons.add(importButton); + jpButtons.add(cancelButton); + + getContentPane().setLayout(new BorderLayout()); + getContentPane().add(trustedCertsPanel, CENTER); + getContentPane().add(jpButtons, SOUTH); + + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent evt) { + closeDialog(); + } + }); + + setResizable(false); + getRootPane().setDefaultButton(importButton); + pack(); + } + + /** + * Shows the selected key pair's certificate. + */ + private void certificateDetailsPressed() { + try { + int i = trustedCertsJList.getSelectedIndex(); + + X509Certificate cert = (X509Certificate) availableTrustedCerts + .get(i); + + ViewCertDetailsDialog viewCertificateDialog = new ViewCertDetailsDialog( + this, "Certificate details", true, cert, null, dnParser); + viewCertificateDialog.setLocationRelativeTo(this); + viewCertificateDialog.setVisible(true); + } catch (Exception ex) { + showMessageDialog(this, + "Failed to obtain certificate details to show", + ALERT_TITLE, WARNING_MESSAGE); + closeDialog(); + } + } + + /** + * Get the trusted certificates selected for import. + */ + public ArrayList<X509Certificate> getTrustedCertificates() { + return selectedTrustedCerts; + } + + /** + * Store the selected trusted certs. + */ + public void importPressed() { + int[] selectedValues = trustedCertsJList.getSelectedIndices(); + selectedTrustedCerts = new ArrayList<>(); + for (int i = 0; i < selectedValues.length; i++) + selectedTrustedCerts.add(availableTrustedCerts + .get(selectedValues[i])); + closeDialog(); + } + + public void cancelPressed() { + /* + * Set selectedTrustCerts to null to indicate that user has cancelled + * the import + */ + selectedTrustedCerts = null; + closeDialog(); + } + + private void closeDialog() { + setVisible(false); + dispose(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/PasswordsTableModel.java ---------------------------------------------------------------------- diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/PasswordsTableModel.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/PasswordsTableModel.java new file mode 100644 index 0000000..30af7b1 --- /dev/null +++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/PasswordsTableModel.java @@ -0,0 +1,226 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.credentialmanager; + +import static javax.swing.JOptionPane.ERROR_MESSAGE; +import static javax.swing.JOptionPane.showMessageDialog; +import static org.apache.taverna.security.credentialmanager.CredentialManager.KeystoreType.KEYSTORE; +import static org.apache.taverna.workbench.ui.credentialmanager.CMStrings.ERROR_TITLE; +import static org.apache.taverna.workbench.ui.credentialmanager.CredentialManagerUI.PASSWORD_ENTRY_TYPE; + +import java.net.URI; +import java.util.TreeMap; + +import javax.swing.JFrame; +import javax.swing.table.AbstractTableModel; + +import org.apache.taverna.lang.observer.Observable; +import org.apache.taverna.lang.observer.Observer; +import org.apache.taverna.security.credentialmanager.CMException; +import org.apache.taverna.security.credentialmanager.CredentialManager; +import org.apache.taverna.security.credentialmanager.KeystoreChangedEvent; +import org.apache.taverna.security.credentialmanager.UsernamePassword; + +import org.apache.log4j.Logger; + +/** + * The table model used to display the Keystore's username/password pair + * entries. + * + * @author Alex Nenadic + */ +@SuppressWarnings("serial") +public class PasswordsTableModel extends AbstractTableModel implements + Observer<KeystoreChangedEvent> { + private static final Logger logger = Logger + .getLogger(PasswordsTableModel.class); + + // Column names + private String[] columnNames; + // Table data + private Object[][] data; + private CredentialManager credManager; + + public PasswordsTableModel(CredentialManager credentialManager) { + credManager = credentialManager; + if (credentialManager == null) { + // Failed to instantiate Credential Manager - warn the user and exit + String sMessage = "Failed to instantiate Credential Manager. "; + logger.error("CM GUI: " + sMessage); + showMessageDialog(new JFrame(), sMessage, ERROR_TITLE, + ERROR_MESSAGE); + return; + } + + data = new Object[0][0]; + columnNames = new String[] { "Entry Type", // type of the Keystore entry + "Service URL", // the service url, part of the actual alias in + // the Keystore + "Username", // username for the service, part of the password + // entry in the Keystore + "Last Modified", // last modified date of the entry + "Password", // the invisible column holding the password value + // of the password entry in the Keystore + "Alias" // the invisible column holding the Keystore alias of + // the entry + }; + + try { + load(); + } catch (CMException cme) { + String sMessage = "Failed to load username and password pairs"; + logger.error(sMessage); + showMessageDialog(new JFrame(), sMessage, ERROR_TITLE, + ERROR_MESSAGE); + return; + } + + // Start observing changes to the Keystore + credManager.addObserver(this); + } + + /** + * Load the PasswordsTableModel with the password entries from the Keystore. + */ + public void load() throws CMException { + // Place password entries' aliases in a tree map to sort them + TreeMap<String, String> aliases = new TreeMap<>(); + + for (String alias : credManager.getAliases(KEYSTORE)) + /* + * We are only interested in username/password entries here. Alias + * for such entries is constructed as "password#"<SERVICE_URL> where + * service URL is the service this username/password pair is to be + * used for. + */ + if (alias.startsWith("password#")) + aliases.put(alias, alias); + + // Create one table row for each password entry + data = new Object[aliases.size()][6]; + + /* + * Iterate through the sorted aliases, retrieving the password entries + * and populating the table model + */ + int iCnt = 0; + for (String alias : aliases.values()) { + /* + * Populate the type column - it is set with an integer but a custom + * cell renderer will cause a suitable icon to be displayed + */ + data[iCnt][0] = PASSWORD_ENTRY_TYPE; + + /* + * Populate the service URL column as a substring of alias from the + * first occurrence of '#' till the end of the string + */ + String serviceURL = alias.substring(alias.indexOf('#') + 1); + data[iCnt][1] = serviceURL; + + /* + * Get the username and password pair from the Keystore. They are + * returned in a single string in format + * <USERNAME><SEPARATOR_CHARACTER><PASSWORD> + */ + UsernamePassword usernamePassword = credManager + .getUsernameAndPasswordForService(URI.create(serviceURL), + false, ""); + String username = usernamePassword.getUsername(); + String password = usernamePassword.getPasswordAsString(); + + // Populate the username column + data[iCnt][2] = username; + + // Populate the last modified date column ("UBER" keystore type + // supports creation date) + // data[iCnt][3] = + // credManager.getEntryCreationDate(CredentialManager.KEYSTORE, + // alias); + + // Populate the invisible password column + data[iCnt][4] = password; + + // Populate the invisible alias column + data[iCnt][5] = alias; + + iCnt++; + } + + fireTableDataChanged(); + } + + /** + * Get the number of columns in the table. + */ + @Override + public int getColumnCount() { + return columnNames.length; + } + + /** + * Get the number of rows in the table. + */ + @Override + public int getRowCount() { + return data.length; + } + + /** + * Get the name of the column at the given position. + */ + @Override + public String getColumnName(int iCol) { + return columnNames[iCol]; + } + + /** + * Get the cell value at the given row and column position. + */ + @Override + public Object getValueAt(int iRow, int iCol) { + return data[iRow][iCol]; + } + + /** + * Get the class at of the cells at the given column position. + */ + @Override + public Class<? extends Object> getColumnClass(int iCol) { + return getValueAt(0, iCol).getClass(); + } + + /** + * Is the cell at the given row and column position editable? + */ + @Override + public boolean isCellEditable(int iRow, int iCol) { + // The table is always read-only + return false; + } + + @Override + public void notify(Observable<KeystoreChangedEvent> sender, + KeystoreChangedEvent message) throws Exception { + // reload the table + if (message.keystoreType.equals(KEYSTORE)) + load(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/SetMasterPasswordDialog.java ---------------------------------------------------------------------- diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/SetMasterPasswordDialog.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/SetMasterPasswordDialog.java new file mode 100644 index 0000000..9fe13a4 --- /dev/null +++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/SetMasterPasswordDialog.java @@ -0,0 +1,188 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.credentialmanager; + +import static java.awt.BorderLayout.CENTER; +import static java.awt.BorderLayout.NORTH; +import static java.awt.BorderLayout.SOUTH; +import static java.awt.Font.PLAIN; +import static javax.swing.BoxLayout.Y_AXIS; +import static javax.swing.JOptionPane.WARNING_MESSAGE; +import static javax.swing.JOptionPane.showMessageDialog; +import static org.apache.taverna.workbench.ui.credentialmanager.CMStrings.WARN_TITLE; + +import java.awt.BorderLayout; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.swing.BoxLayout; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JPasswordField; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; +import javax.swing.border.EtchedBorder; + +import org.apache.taverna.workbench.helper.NonBlockedHelpEnabledDialog; + +/** + * Dialog used for user to set a master password for Credential Manager. + * + * @author Alex Nenadic + */ +@SuppressWarnings("serial") +public class SetMasterPasswordDialog extends NonBlockedHelpEnabledDialog { + /** Password entry field */ + private JPasswordField passwordField; + /** Password confirmation entry field */ + private JPasswordField passwordConfirmField; + /** The entered password */ + private String password = null; + /** Instructions for the user */ + private String instructions; + + public SetMasterPasswordDialog(JFrame parent, String title, boolean modal, + String instructions) { + super(parent, title, modal); + this.instructions = instructions; + initComponents(); + } + + private void initComponents() { + getContentPane().setLayout(new BorderLayout()); + + JLabel instructionsLabel = new JLabel(instructions); + instructionsLabel.setFont(new Font(null, PLAIN, 11)); + + JPanel instructionsPanel = new JPanel(); + instructionsPanel.setLayout(new BoxLayout(instructionsPanel, Y_AXIS)); + instructionsPanel.add(instructionsLabel); + instructionsPanel.setBorder(new EmptyBorder(10, 5, 10, 0)); + + JLabel passwordLabel = new JLabel("Master password"); + passwordLabel.setBorder(new EmptyBorder(0, 5, 0, 0)); + + JLabel passwordConfirmLabel = new JLabel("Confirm master password"); + passwordConfirmLabel.setBorder(new EmptyBorder(0, 5, 0, 0)); + + passwordField = new JPasswordField(15); + passwordConfirmField = new JPasswordField(15); + + JPanel passwordPanel = new JPanel(new GridLayout(2, 2, 5, 5)); + passwordPanel.add(passwordLabel); + passwordPanel.add(passwordField); + passwordPanel.add(passwordConfirmLabel); + passwordPanel.add(passwordConfirmField); + + JPanel mainPanel = new JPanel(new BorderLayout()); + mainPanel.setBorder(new CompoundBorder(new EmptyBorder(10, 10, 10, 10), + new EtchedBorder())); + mainPanel.add(instructionsPanel, NORTH); + mainPanel.add(passwordPanel, CENTER); + + JButton okButton = new JButton("OK"); + okButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + okPressed(); + } + }); + + JButton cancelButton = new JButton("Cancel"); + cancelButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent evt) { + cancelPressed(); + } + }); + JPanel buttonsPanel = new JPanel(new FlowLayout(FlowLayout.CENTER)); + buttonsPanel.add(okButton); + buttonsPanel.add(cancelButton); + + getContentPane().add(mainPanel, CENTER); + getContentPane().add(buttonsPanel, SOUTH); + + addWindowListener(new WindowAdapter() { + @Override + public void windowClosing(WindowEvent evt) { + closeDialog(); + } + }); + + setResizable(false); + getRootPane().setDefaultButton(okButton); + pack(); + } + + public String getPassword() { + return password; + } + + /** + * Check that the user has entered a non-empty password and store the new + * password. + */ + private boolean checkPassword() { + String firstPassword = new String(passwordField.getPassword()); + String confirmPassword = new String(passwordConfirmField.getPassword()); + + if (!firstPassword.equals(confirmPassword)) { + showMessageDialog(this, "The passwords do not match", WARN_TITLE, + WARNING_MESSAGE); + return false; + } + if (firstPassword.isEmpty()) { + // passwords match but are empty + showMessageDialog(this, "The password cannot be empty", WARN_TITLE, + WARNING_MESSAGE); + return false; + } + + // passwords match and not empty + password = firstPassword; + return true; + } + + private void okPressed() { + if (checkPassword()) + closeDialog(); + } + + private void cancelPressed() { + /* + * Set the password to null as it might have changed in the meantime if + * user entered something then cancelled. + */ + password = null; + closeDialog(); + } + + private void closeDialog() { + setVisible(false); + dispose(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/TableCellRenderer.java ---------------------------------------------------------------------- diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/TableCellRenderer.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/TableCellRenderer.java new file mode 100644 index 0000000..ad88ac0 --- /dev/null +++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/TableCellRenderer.java @@ -0,0 +1,112 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.credentialmanager; + +import static org.apache.taverna.workbench.ui.credentialmanager.CredentialManagerUI.KEY_PAIR_ENTRY_TYPE; +import static org.apache.taverna.workbench.ui.credentialmanager.CredentialManagerUI.PASSWORD_ENTRY_TYPE; +import static org.apache.taverna.workbench.ui.credentialmanager.CredentialManagerUI.TRUST_CERT_ENTRY_TYPE; + +import java.awt.Component; +//import java.text.DateFormat; +//import java.util.Date; + +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.border.EmptyBorder; +import javax.swing.table.DefaultTableCellRenderer; +//import net.sf.taverna.t2.workbench.ui.credentialmanager.KeyPairsTableModel; +//import net.sf.taverna.t2.workbench.ui.credentialmanager.PasswordsTableModel; +//import net.sf.taverna.t2.workbench.ui.credentialmanager.TrustedCertsTableModel; + +/** + * Custom cell renderer for the cells of the tables displaying + * Keystore/Truststore contents. + * + * @author Alex Nenadic + */ +public class TableCellRenderer extends DefaultTableCellRenderer { + private static final long serialVersionUID = -3983986682794010259L; + + private final ImageIcon passwordEntryIcon = new ImageIcon( + TableCellRenderer.class.getResource("/images/table/key_entry.png")); + private final ImageIcon keypairEntryIcon = new ImageIcon( + TableCellRenderer.class + .getResource("/images/table/keypair_entry.png")); + private final ImageIcon trustcertEntryIcon = new ImageIcon( + TableCellRenderer.class + .getResource("/images/table/trustcert_entry.png")); + + /** + * Get the rendered cell for the supplied value and column. + */ + @Override + public Component getTableCellRendererComponent(JTable keyStoreTable, + Object value, boolean bIsSelected, boolean bHasFocus, int iRow, + int iCol) { + JLabel cell = (JLabel) super.getTableCellRendererComponent( + keyStoreTable, value, bIsSelected, bHasFocus, iRow, iCol); + + if (value != null) { + // Type column - display an icon representing the type + if (iCol == 0) + configureTypeColumn(value, cell); + // Last Modified column - format date (if date supplied) + /*else if (((keyStoreTable.getModel() instanceof PasswordsTableModel) && (iCol == 3)) || + ((keyStoreTable.getModel() instanceof KeyPairsTableModel) && (iCol == 4))|| + ((keyStoreTable.getModel() instanceof TrustedCertsTableModel) && (iCol == 4))){ + if (value instanceof Date) { + // Include timezone + cell.setText(DateFormat.getDateTimeInstance(DateFormat.MEDIUM, + DateFormat.LONG).format((Date) value)); + } else { + cell.setText(value.toString()); + } + }*/ + // Other columns - just use their text values + else + cell.setText(value.toString()); + } + + cell.setBorder(new EmptyBorder(0, 5, 0, 5)); + return cell; + } + + private void configureTypeColumn(Object value, JLabel cell) { + ImageIcon icon = null; + // The cell is in the first column of Passwords table + if (PASSWORD_ENTRY_TYPE.equals(value)) { + icon = passwordEntryIcon; // key (i.e. password) entry image + } + // The cell is in the first column of Key Pairs table + else if (KEY_PAIR_ENTRY_TYPE.equals(value)) { + icon = keypairEntryIcon; // key pair entry image + } + // The cell is in the first column of Trusted Certificates table + else if (TRUST_CERT_ENTRY_TYPE.equals(value)) { + icon = trustcertEntryIcon; // trust. certificate entry image + } + + cell.setIcon(icon); + cell.setText(""); + cell.setVerticalAlignment(CENTER); + cell.setHorizontalAlignment(CENTER); + } +} http://git-wip-us.apache.org/repos/asf/incubator-taverna-workbench/blob/a9a52bd5/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/TableHeaderRenderer.java ---------------------------------------------------------------------- diff --git a/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/TableHeaderRenderer.java b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/TableHeaderRenderer.java new file mode 100644 index 0000000..11d7d3c --- /dev/null +++ b/taverna-credential-manager-ui/src/main/java/org/apache/taverna/workbench/ui/credentialmanager/TableHeaderRenderer.java @@ -0,0 +1,94 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +package org.apache.taverna.workbench.ui.credentialmanager; + +import static javax.swing.border.BevelBorder.RAISED; + +import java.awt.Component; + +import javax.swing.ImageIcon; +import javax.swing.JLabel; +import javax.swing.JTable; +import javax.swing.border.BevelBorder; +import javax.swing.border.CompoundBorder; +import javax.swing.border.EmptyBorder; +import javax.swing.table.DefaultTableCellRenderer; + +/** + * Custom cell renderer for the headers of the tables displaying + * the Keystore/Truststore contents. + */ +@SuppressWarnings("serial") +public class TableHeaderRenderer extends DefaultTableCellRenderer { + private final ImageIcon entryTypeIcon = new ImageIcon( + TableHeaderRenderer.class + .getResource("/images/table/entry_heading.png")); + + @Override + public Component getTableCellRendererComponent(JTable jtKeyStoreTable, + Object value, boolean bIsSelected, boolean bHasFocus, int iRow, + int iCol) { + // Get header renderer + JLabel header = (JLabel) jtKeyStoreTable.getColumnModel().getColumn(iCol).getHeaderRenderer(); + + // The entry type header contains an icon for every table + if (iCol == 0) { + header.setText(""); + header.setIcon(entryTypeIcon); // entry type icon (header for the first column of the table) + header.setHorizontalAlignment(CENTER); + header.setVerticalAlignment(CENTER); + header.setToolTipText("Entry type"); + } + // All other headers contain text + else { + header.setText((String) value); + header.setHorizontalAlignment(LEFT); + + // Passwords table + if (jtKeyStoreTable.getModel() instanceof PasswordsTableModel){ + if (iCol == 1) //Service URL column + header.setToolTipText("URL of the service username and password will be used for"); + else if (iCol == 2) // Username column + header.setToolTipText("Username for the service"); + } + // Key pairs table + else if (jtKeyStoreTable.getModel() instanceof KeyPairsTableModel) { + if (iCol == 1) // Owner + header.setToolTipText("Certificate's owner"); + else if (iCol == 2) // Issuer + header.setToolTipText("Certificate's issuer"); + else if (iCol == 3) // Serial number + header.setToolTipText("Certificate's serial number"); + } + // Trusted certs table + else if (jtKeyStoreTable.getModel() instanceof TrustedCertsTableModel) { + if (iCol == 1) // Owner + header.setToolTipText("Certificate's owner"); + else if (iCol == 2) // Issuer + header.setToolTipText("Certificate's issuer"); + else if (iCol == 3) // Serial number + header.setToolTipText("Certificate's serial number"); + } + } + header.setBorder(new CompoundBorder(new BevelBorder(RAISED), + new EmptyBorder(0, 5, 0, 5))); + return header; + } +}
