Coverage Report - org.openpermis.editor.policy.view.RoleAssignmentWizard
 
Classes in this File Line Coverage Branch Coverage Complexity
RoleAssignmentWizard
0%
0/199
0%
0/32
2.333
RoleAssignmentWizard$1
0%
0/8
0%
0/2
2.333
RoleAssignmentWizard$2
0%
0/22
0%
0/4
2.333
RoleAssignmentWizard$3
0%
0/7
N/A
2.333
RoleAssignmentWizard$4
0%
0/3
N/A
2.333
RoleAssignmentWizard$5
0%
0/8
0%
0/4
2.333
RoleAssignmentWizard$6
0%
0/3
N/A
2.333
 
 1  
 /*
 2  
  * Copyright (c) 2009, Swiss Federal Department of Defence Civil Protection and Sport
 3  
  *                     (http://www.vbs.admin.ch)
 4  
  * Copyright (c) 2009, Ergon Informatik AG (http://www.ergon.ch)
 5  
  * All rights reserved.
 6  
  *
 7  
  * Licensed under the Open Permis License which accompanies this distribution,
 8  
  * and is available at http://www.openpermis.org/BSDlicenceKent.txt
 9  
  */
 10  
 package org.openpermis.editor.policy.view;
 11  
 
 12  
 import java.awt.BorderLayout;
 13  
 import java.awt.Color;
 14  
 import java.awt.Component;
 15  
 import java.awt.Dialog;
 16  
 import java.awt.Dimension;
 17  
 import java.awt.Frame;
 18  
 import java.awt.Graphics;
 19  
 import java.awt.Window;
 20  
 import java.awt.event.ActionEvent;
 21  
 import java.awt.event.ActionListener;
 22  
 import java.awt.event.KeyEvent;
 23  
 import java.awt.event.WindowAdapter;
 24  
 import java.awt.event.WindowEvent;
 25  
 import java.io.BufferedInputStream;
 26  
 import java.io.BufferedOutputStream;
 27  
 import java.io.File;
 28  
 import java.io.FileInputStream;
 29  
 import java.io.FileNotFoundException;
 30  
 import java.io.FileOutputStream;
 31  
 import java.io.IOException;
 32  
 import java.io.InputStream;
 33  
 import java.math.BigInteger;
 34  
 import java.security.cert.CertificateEncodingException;
 35  
 import java.util.ArrayList;
 36  
 import java.util.Date;
 37  
 import java.util.List;
 38  
 
 39  
 import javax.security.auth.x500.X500Principal;
 40  
 import javax.swing.ActionMap;
 41  
 import javax.swing.InputMap;
 42  
 import javax.swing.JButton;
 43  
 import javax.swing.JComponent;
 44  
 import javax.swing.JDialog;
 45  
 import javax.swing.JFileChooser;
 46  
 import javax.swing.JLabel;
 47  
 import javax.swing.JOptionPane;
 48  
 import javax.swing.JPanel;
 49  
 import javax.swing.JPasswordField;
 50  
 import javax.swing.JRootPane;
 51  
 import javax.swing.JScrollPane;
 52  
 import javax.swing.JTextArea;
 53  
 import javax.swing.JTextField;
 54  
 import javax.swing.KeyStroke;
 55  
 import javax.swing.SwingConstants;
 56  
 import javax.swing.SwingUtilities;
 57  
 import javax.swing.UIManager;
 58  
 import javax.swing.border.Border;
 59  
 import javax.swing.border.EmptyBorder;
 60  
 import javax.swing.event.DocumentEvent;
 61  
 import javax.swing.event.DocumentListener;
 62  
 import javax.swing.text.JTextComponent;
 63  
 
 64  
 import org.bouncycastle.asn1.ASN1Encodable;
 65  
 import org.bouncycastle.x509.X509Attribute;
 66  
 import org.jdesktop.application.Action;
 67  
 import org.jdesktop.application.ApplicationContext;
 68  
 import org.jdesktop.application.ResourceMap;
 69  
 import org.jdesktop.observablecollections.ObservableCollections;
 70  
 import org.jdesktop.observablecollections.ObservableList;
 71  
 import org.jdesktop.swingx.JXHeader;
 72  
 import org.jdesktop.swingx.JXHeader.IconPosition;
 73  
 import org.slf4j.Logger;
 74  
 import org.slf4j.LoggerFactory;
 75  
 
 76  
 import com.jgoodies.forms.factories.ComponentFactory;
 77  
 import com.jgoodies.forms.factories.DefaultComponentFactory;
 78  
 import com.jgoodies.forms.layout.FormLayout;
 79  
 
 80  
 import org.openpermis.cert.Attribute;
 81  
 import org.openpermis.cert.AttributeCertificate;
 82  
 import org.openpermis.cert.AttributeCertificateGenerator;
 83  
 import org.openpermis.cert.KeyStoreReader;
 84  
 import org.openpermis.cert.KeyStoreReaderException;
 85  
 import org.openpermis.cert.RoleAttribute;
 86  
 import org.openpermis.cert.RoleAttribute.RoleDefinition;
 87  
 import org.openpermis.editor.policy.Application;
 88  
 import org.openpermis.editor.policy.PolicyFileFilter;
 89  
 import org.openpermis.editor.policy.gui.SmartConstraints;
 90  
 import org.openpermis.editor.policy.gui.checklist.CheckList;
 91  
 import org.openpermis.policy.Role;
 92  
 import org.openpermis.policy.bean.PolicyBean;
 93  
 
 94  
 /**
 95  
  * Wizard to create an attribute certificates assigning roles to a subject.
 96  
  * @since 0.3.0
 97  
  */
 98  0
 public class RoleAssignmentWizard {
 99  
 
 100  
         //---- Static
 101  
 
 102  
         /**
 103  
          * The logger of this class.
 104  
          * @since 0.3.0
 105  
          */
 106  0
         private static final Logger LOGGER =
 107  
                 LoggerFactory.getLogger(RoleAssignmentWizard.class);
 108  
 
 109  
 
 110  
         /**
 111  
          * The number of columns in a text field.
 112  
          * @since 0.3.0
 113  
          */
 114  
         private static final int TEXT_FIELD_COLUMNS = 25;
 115  
 
 116  
         /**
 117  
          * Client property for chooser buttons that contains the next focus field.
 118  
          * @since 0.3.0
 119  
          */
 120  
         private static final String NEXT_FOCUS = "chooserNextFocus";
 121  
 
 122  
         /**
 123  
          * The text on the directory chooser buttons.
 124  
          * @since 0.3.0
 125  
          */
 126  
         private static final String CHOOSER_TEXT = "...";
 127  
 
 128  
         /**
 129  
          * The content border for the wizard.
 130  
          * @since 0.3.0
 131  
          */
 132  0
         private static final Border BORDER = new EmptyBorder(1, 0, 0, 1) {
 133  
                 private static final long serialVersionUID = 2189890664318454568L;
 134  
                 @Override
 135  0
                 public void paintBorder (Component c, Graphics g, int x, int y, int width, int height) {
 136  0
                         final Color color = g.getColor();
 137  0
                         final Color shadow = UIManager.getColor("Separator.shadow");
 138  0
                         g.setColor(shadow == null ? Color.GRAY : shadow);
 139  0
                         g.drawLine(x, y, x + width, y);
 140  0
                         g.drawLine(x, y + height - 1, x + width, y + height - 1);
 141  0
                         g.setColor(color);
 142  0
                 }
 143  
         };
 144  
         
 145  
         /**
 146  
          * The size of the content panel.
 147  
          * @since 0.3.0
 148  
          */
 149  0
         private static final Dimension CONTENT_PANEL_DIMENSION = new Dimension(750, 400);
 150  
         
 151  
         /**
 152  
          * The preferred size of the certificate browser.
 153  
          * @since 0.3.0
 154  
          */
 155  0
         private static final Dimension BROWSER_PREFERRED_SIZE = new Dimension(300, 300);
 156  
 
 157  
 
 158  
         //---- State
 159  
 
 160  
         /**
 161  
          * The action map attached to this view instance.
 162  
          * @since 0.3.0
 163  
          */
 164  
         private final ActionMap actionMap;
 165  
 
 166  
         /**
 167  
          * The resource map attached to this view instance.
 168  
          * @since 0.3.0
 169  
          */
 170  
         private final ResourceMap resourceMap;
 171  
 
 172  
         /**
 173  
          * Text field for the selection of the attribute certificate to browse file.
 174  
          * @since 0.3.0
 175  
          */
 176  
         private final JTextField acPath;
 177  
 
 178  
         /**
 179  
          * Text area showing the ace content.
 180  
          * @since 0.3.0
 181  
          */
 182  
         private final JTextArea aceContentArea;
 183  
 
 184  
         /**
 185  
          * Text field for the selection of the PKCS12 file.
 186  
          * @since 0.3.0
 187  
          */
 188  
         private final JTextField pkcs12File;
 189  
 
 190  
         /**
 191  
          * The wizard content pane.
 192  
          * @since 0.3.0
 193  
          */
 194  
         private final JPanel content;
 195  
 
 196  
         /**
 197  
          * Password field for the PKCS12 password.
 198  
          * @since 0.3.0
 199  
          */
 200  
         private final JPasswordField password;
 201  
 
 202  
         /**
 203  
          * Subject field.
 204  
          * @since 0.3.0
 205  
          */
 206  
         private final JTextField subject;
 207  
         
 208  
         /**
 209  
          * The list of roles to choose from.
 210  
          * @since 0.3.0
 211  
          */
 212  
         private final CheckList<Role> roleList;
 213  
         
 214  
         /**
 215  
          * The list of the actually selected roles.
 216  
          * @since 0.3.0
 217  
          */
 218  
         private final ObservableList<Role> selectedRoles;
 219  
 
 220  
         /**
 221  
          * Text field for the selection of the output file created.
 222  
          * @since 0.3.0
 223  
          */
 224  
         private final JTextField aceFile;
 225  
 
 226  
         /**
 227  
          * The default button of the wizard.
 228  
          * @since 0.3.0
 229  
          */
 230  
         private final JButton defaultButton;
 231  
 
 232  
         /**
 233  
          * The wizard dialog component.
 234  
          * @since 0.3.0
 235  
          */
 236  
         private JDialog dialog;
 237  
 
 238  
 
 239  
         //---- Constructors
 240  
 
 241  
         /**
 242  
          * Creates a wizard to create an attribute certificates assigning roles to a subject.
 243  
          * @param context the application context used to lookup the action and resource map.
 244  
          * @param policy the policy to export to the ace file.
 245  
          * @since 0.3.0
 246  
          */
 247  0
         public RoleAssignmentWizard (ApplicationContext context, PolicyBean policy) {
 248  0
                 this.actionMap = context.getActionMap(getClass(), this);
 249  0
                 this.resourceMap = context.getResourceMap(getClass());
 250  0
                 this.content = new JPanel(new BorderLayout());
 251  0
                 final JXHeader header = new JXHeader(
 252  
                         this.resourceMap.getString("View.title"),
 253  
                         this.resourceMap.getString("View.description")
 254  
                 );
 255  0
                 header.setIcon(this.resourceMap.getIcon("View.icon"));
 256  0
                 header.setIconPosition(IconPosition.LEFT);
 257  0
                 this.content.add(header, BorderLayout.PAGE_START);
 258  0
                 final FormLayout layout = new FormLayout(
 259  
                         "4dlu, pref, 4dlu, pref:grow, pref, 4dlu",
 260  
                         "8dlu, pref, 4dlu, pref, 2dlu, pref, 4dlu:grow, pref," +
 261  
                         "4dlu, pref, 4dlu, pref, 4dlu, pref, 4dlu, pref, 4dlu," +
 262  
                         "pref, 4dlu, pref, 8dlu, pref"
 263  
                 );
 264  0
                 final JPanel wizard = new JPanel(layout);
 265  0
                 wizard.setBorder(BORDER);
 266  0
                 final SmartConstraints cc = new SmartConstraints(2, 2);
 267  0
                 wizard.add(createSeparator("acBrowser"), cc.yw(2, layout.getColumnCount() - 2));
 268  0
                 cc.y(2);
 269  0
                 final JLabel acLabel = createLabel("aceFile");
 270  0
                 wizard.add(acLabel, cc.x(2));
 271  0
                 this.acPath = createTextField(acLabel);
 272  0
                 this.aceContentArea = new JTextArea();
 273  0
                 this.aceContentArea.setEditable(false);
 274  0
                 this.aceContentArea.setLineWrap(true);
 275  
 
 276  0
                 this.acPath.getDocument().addDocumentListener(new DocumentListener() {
 277  
 
 278  
                         public void changedUpdate (DocumentEvent arg0) {
 279  
                                 // Required by DocumentListener.
 280  0
                         }
 281  
 
 282  
                         public void insertUpdate (DocumentEvent arg0) {
 283  
                                 try {
 284  
                                         FileInputStream is;
 285  0
                                         is = new FileInputStream(new File(RoleAssignmentWizard.this.acPath.getText()));
 286  0
                                         AttributeCertificate ac = new AttributeCertificate(is);
 287  0
                                         StringBuilder stringBuilder = new StringBuilder();
 288  0
                                         stringBuilder.append(ac.getHolder().getEntityNames()[0] + "\n");
 289  0
                                         for (X509Attribute a : ac.getAttributes()) {
 290  0
                                                 for (ASN1Encodable e : a.getValues()) {
 291  0
                                                         stringBuilder.append(e.toString() + "\n");
 292  
                                                 }
 293  
                                         }
 294  0
                                         RoleAssignmentWizard.this.aceContentArea.setText(stringBuilder.toString());
 295  0
                                 } catch (FileNotFoundException e) {
 296  0
                                         showErrorDialog("fileNotFoundError", e.getMessage());
 297  0
                                         RoleAssignmentWizard.this.aceContentArea.setText("");
 298  0
                                 } catch (IOException e) {
 299  0
                                         showErrorDialog("fileNotFoundError", e.getMessage());
 300  0
                                         RoleAssignmentWizard.this.aceContentArea.setText("");
 301  0
                                 } catch (IllegalArgumentException e) {
 302  0
                                         showErrorDialog("fileNotFoundError", e.getMessage());
 303  0
                                         RoleAssignmentWizard.this.aceContentArea.setText("");
 304  0
                                 }
 305  0
                         }
 306  
 
 307  0
                         public void removeUpdate (DocumentEvent arg0) {
 308  
                                 // Required by DocumentListener.
 309  0
                         }
 310  
 
 311  
                 });
 312  
                 
 313  0
                 wizard.add(this.acPath, cc.x(1));
 314  0
                 final JButton acFileChooser =
 315  
                         createChooser(this.acPath, JFileChooser.OPEN_DIALOG, null);
 316  0
                 wizard.add(acFileChooser, cc.x(1));
 317  0
                 cc.y(2);
 318  0
                 wizard.add(new JLabel(""), cc.x(2));
 319  0
                 JScrollPane scrollPane = new JScrollPane(this.aceContentArea);
 320  0
                 scrollPane.setPreferredSize(BROWSER_PREFERRED_SIZE);
 321  0
                 wizard.add(scrollPane, cc.x(2));
 322  0
                 cc.y(2);
 323  
 
 324  0
                 wizard.add(createSeparator("input"), cc.yw(2, layout.getColumnCount() - 2));
 325  0
                 final JLabel pkcs12FileLabel = createLabel("pkcs12File");
 326  0
                 wizard.add(pkcs12FileLabel, cc.x(2));
 327  0
                 this.pkcs12File = createTextField(pkcs12FileLabel);
 328  0
                 wizard.add(this.pkcs12File, cc.x(1));
 329  0
                 final JButton pkcs12FileChooser =
 330  
                         createChooser(this.pkcs12File, JFileChooser.OPEN_DIALOG, null);
 331  0
                 wizard.add(pkcs12FileChooser, cc.y(2));
 332  0
                 final JLabel passwordLabel = createLabel("password");
 333  0
                 wizard.add(passwordLabel, cc.x(2));
 334  0
                 this.password = createPasswordField(passwordLabel);
 335  0
                 pkcs12FileChooser.putClientProperty(NEXT_FOCUS, this.password);
 336  0
                 wizard.add(this.password, cc.y(2));
 337  0
                 final JLabel subjectLabel = createLabel("subject");
 338  0
                 wizard.add(subjectLabel, cc.x(2));
 339  0
                 this.subject = createTextField(subjectLabel);
 340  0
                 this.subject.setEditable(true);
 341  0
                 wizard.add(this.subject, cc.x(1));
 342  0
                 cc.y(2);
 343  
                 
 344  
                 
 345  0
                 this.roleList = new CheckList<Role>();
 346  0
                 this.selectedRoles = ObservableCollections.observableList(new ArrayList<Role>());
 347  0
                 this.roleList.bind(
 348  
                         ObservableCollections.observableList(policy.getRoleRefList()),
 349  
                         this.selectedRoles
 350  
                 );
 351  0
                 this.roleList.validate();
 352  
                 
 353  0
                 final JLabel rolesLabel = createLabel("roles");
 354  0
                 wizard.add(rolesLabel, cc.x(2));
 355  0
                 wizard.add(this.roleList, cc.x(1));
 356  0
                 cc.y(2);
 357  
 
 358  0
                 wizard.add(createSeparator("output"), cc.yw(2, layout.getColumnCount() - 2));
 359  0
                 final JLabel aceFileLabel = createLabel("aceFile");
 360  0
                 wizard.add(aceFileLabel, cc.x(2));
 361  0
                 this.aceFile = createTextField(aceFileLabel);
 362  0
                 wizard.add(this.aceFile, cc.x(1));
 363  0
                 final JButton aceFileChooser =
 364  
                         createChooser(this.aceFile, JFileChooser.SAVE_DIALOG, PolicyFileFilter.ACE_FILE_FILTER);
 365  0
                 wizard.add(aceFileChooser, cc.y(2));
 366  0
                 this.content.add(wizard, BorderLayout.CENTER);
 367  0
                 final JPanel buttons = new JPanel(
 368  
                         new FormLayout(
 369  
                                 "4dlu:grow, pref, 2dlu, pref, 4dlu",
 370  
                                 "4dlu, pref, 4dlu"
 371  
                         )
 372  
                 );
 373  0
                 cc.reset(2, 2);
 374  0
                 buttons.add(new JButton(this.actionMap.get("cancel")), cc.x(2));
 375  0
                 this.defaultButton = new JButton(this.actionMap.get("execute"));
 376  0
                 aceFileChooser.putClientProperty(NEXT_FOCUS, this.defaultButton);
 377  0
                 buttons.add(this.defaultButton, cc.y(1));
 378  0
                 this.content.add(buttons, BorderLayout.PAGE_END);
 379  0
                 this.resourceMap.injectComponents(this.content);
 380  0
         }
 381  
 
 382  
         //---- Methods
 383  
 
 384  
         /**
 385  
          * Updates the actions according to the values in the wizard fields.
 386  
          * @since 0.3.0
 387  
          */
 388  
         private final void updateActions () {
 389  0
                 final boolean validPkcs12File = new File(this.pkcs12File.getText()).isFile();
 390  0
                 final File aceParentFile = new File(this.aceFile.getText()).getParentFile();
 391  0
                 final boolean validAceFile = aceParentFile != null && aceParentFile.isDirectory();
 392  0
                 this.actionMap.get("execute").setEnabled(validPkcs12File && validAceFile);
 393  0
         }
 394  
 
 395  
         /**
 396  
          * Configures the specified text component.
 397  
          * <p>Changes to the document of the text component will cause the actions of the wizard
 398  
          * to be updated (see {@link #updateActions()}. In addition a label for the text field
 399  
          * is configured.</p>
 400  
          * @param <T> the type of text component to configure.
 401  
          * @param component the text component to configure.
 402  
          * @param label the label of the text component, must not be {@code null}.
 403  
          * @return the text component passed in for fluent use.
 404  
          * @since 0.3.0
 405  
          */
 406  
         private final <T extends JTextComponent> T configure (T component, JLabel label) {
 407  0
                 component.getDocument().addDocumentListener(
 408  
                         new DocumentListener() {
 409  
                                 public void changedUpdate (DocumentEvent e) {
 410  0
                                         updateActions();
 411  0
                                 }
 412  
                                 public void insertUpdate (DocumentEvent e) {
 413  0
                                         updateActions();
 414  0
                                 }
 415  0
                                 public void removeUpdate (DocumentEvent e) {
 416  0
                                         updateActions();
 417  0
                                 }
 418  
                         }
 419  
                 );
 420  0
                 label.setLabelFor(component);
 421  0
                 return component;
 422  
         }
 423  
 
 424  
         /**
 425  
          * Creates a named separator for automated translation.
 426  
          * @param name the name of the separator.
 427  
          * @return the separator created.
 428  
          * @since 0.3.0
 429  
          */
 430  
         private final JComponent createSeparator (String name) {
 431  0
                 final ComponentFactory factory = DefaultComponentFactory.getInstance();
 432  0
                 final JComponent separator = factory.createSeparator(name, SwingConstants.LEFT);
 433  0
                 for (Component child : separator.getComponents()) {
 434  0
                         if (child instanceof JLabel) {
 435  0
                                 ((JLabel) child).setName(name);
 436  
                         }
 437  
                 }
 438  0
                 return separator;
 439  
         }
 440  
 
 441  
         /**
 442  
          * Creates a named label for automated translation.
 443  
          * @param name the name of the label.
 444  
          * @return the label created.
 445  
          * @since 0.3.0
 446  
          */
 447  
         private final JLabel createLabel (String name) {
 448  0
                 final JLabel label = new JLabel(name);
 449  0
                 label.setName(name);
 450  0
                 return label;
 451  
         }
 452  
 
 453  
         /**
 454  
          * Creates and configures a text field.
 455  
          * @param label the label of the text field.
 456  
          * @return the text field created.
 457  
          * @since 0.3.0
 458  
          */
 459  
         private final JTextField createTextField (JLabel label) {
 460  0
                 final JTextField textField = configure(new JTextField(TEXT_FIELD_COLUMNS), label);
 461  0
                 textField.setEditable(false);
 462  0
                 return textField;
 463  
         }
 464  
 
 465  
         /**
 466  
          * Creates and configures a password field.
 467  
          * @param label the label of the password field.
 468  
          * @return the password field created.
 469  
          * @since 0.3.0
 470  
          */
 471  
         private final JPasswordField createPasswordField (JLabel label) {
 472  0
                 return configure(new JPasswordField(TEXT_FIELD_COLUMNS), label);
 473  
         }
 474  
 
 475  
         /**
 476  
          * Creates a file chooser button for the specified target field.
 477  
          * @param target the field to store the chosen file to.
 478  
          * @param type the file chooser type, either {@link JFileChooser#OPEN_DIALOG} or
 479  
          * {@link JFileChooser#SAVE_DIALOG}.
 480  
          * @param filter the file filter to use.
 481  
          * @return the button created.
 482  
          * @since 0.3.0
 483  
          */
 484  
         private final JButton createChooser (
 485  
                 final JTextField target, final int type, final PolicyFileFilter filter
 486  
         ) {
 487  0
                 final JButton chooser = new JButton(CHOOSER_TEXT) {
 488  
                         private static final long serialVersionUID = -3525515562208051410L;
 489  
                         @Override
 490  0
                         public Dimension getPreferredSize () {
 491  0
                                 final Dimension size = super.getPreferredSize();
 492  0
                                 return new Dimension(size.width, target.getPreferredSize().height);
 493  
                         }
 494  
                 };
 495  0
                 chooser.addActionListener(
 496  
                         new ActionListener() {
 497  0
                                 public void actionPerformed (ActionEvent e) {
 498  0
                                         final File file = Application.getInstance().chooseFile(type, false, filter);
 499  0
                                         if (file != null) {
 500  0
                                                 target.setText(file.getAbsolutePath());
 501  0
                                                 final JComponent focus = (JComponent) chooser.getClientProperty(NEXT_FOCUS);
 502  0
                                                 if (focus != null) {
 503  0
                                                         focus.requestFocusInWindow();
 504  
                                                 }
 505  
                                         }
 506  0
                                 }
 507  
                         }
 508  
                 );
 509  0
                 return chooser;
 510  
         }
 511  
 
 512  
         /**
 513  
          * Shows an error dialog with the specified title, message and paramters.
 514  
          * @param key translation key for the title.
 515  
          * @param args optional parameters for the title and message.
 516  
          * @since 0.3.0
 517  
          */
 518  
         protected void showErrorDialog (String key, Object... args) {
 519  0
                 showErrorDialog(this.dialog, key, args);
 520  0
         }
 521  
 
 522  
         /**
 523  
          * Shows an error dialog with the specified title, message and paramters.
 524  
          * @param parent the parent component to show the error dialog for.
 525  
          * @param key translation key for the title.
 526  
          * @param args optional parameters for the title and message.
 527  
          * @since 0.3.0
 528  
          */
 529  
         protected void showErrorDialog (Component parent, String key, Object... args) {
 530  0
                 JOptionPane.showMessageDialog(
 531  
                         parent,
 532  
                         this.resourceMap.getString(key + ".message", args),
 533  
                         this.resourceMap.getString(key + ".title", args),
 534  
                         JOptionPane.ERROR_MESSAGE
 535  
                 );
 536  0
         }
 537  
 
 538  
         /**
 539  
          * Starts the wizard.
 540  
          * @param parent the parent component of the dialog.
 541  
          * @since 0.3.0
 542  
          */
 543  
         public void show (Component parent) {
 544  0
                 this.pkcs12File.setText("");
 545  0
                 this.password.setText("");
 546  0
                 this.aceFile.setText("");
 547  0
                 updateActions();
 548  0
                 final Window window = parent == null ? null : SwingUtilities.getWindowAncestor(parent);
 549  0
                 final String title = this.resourceMap.getString("View.title");
 550  0
                 if (window instanceof Frame) {
 551  0
                         this.dialog = new JDialog((Frame) window, title, true);
 552  0
                 } else if (window instanceof Dialog) {
 553  0
                         this.dialog = new JDialog((Dialog) window, title, true);
 554  
                 } else {
 555  0
                         this.dialog = new JDialog((Frame) null, title, true);
 556  
                 }
 557  0
                 final JRootPane root = this.dialog.getRootPane();
 558  0
                 final KeyStroke enterKey = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false);
 559  0
                 final KeyStroke escapeKey = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false);
 560  0
                 final InputMap focusAncestorInputMap =
 561  
                         root.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
 562  0
                 focusAncestorInputMap.put(enterKey, "execute");
 563  0
                 focusAncestorInputMap.put(escapeKey, "cancel");
 564  0
                 root.getActionMap().put("execute", this.actionMap.get("execute"));
 565  0
                 root.getActionMap().put("cancel", this.actionMap.get("cancel"));
 566  0
                 root.setDefaultButton(this.defaultButton);
 567  0
                 this.dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
 568  0
                 this.dialog.addWindowListener(
 569  
                         new WindowAdapter() {
 570  
                                 @Override
 571  0
                                 public void windowClosing (WindowEvent e) {
 572  0
                                         RoleAssignmentWizard.this.actionMap.get("cancel").actionPerformed(null);
 573  0
                                 }
 574  
                         }
 575  
                 );
 576  
 
 577  0
                 this.content.setSize(CONTENT_PANEL_DIMENSION);
 578  0
                 this.dialog.setContentPane(this.content);
 579  0
                 this.dialog.pack();
 580  0
                 this.dialog.setLocationRelativeTo(parent);
 581  0
                 this.dialog.setVisible(true);
 582  0
         }
 583  
 
 584  
         /**
 585  
          * Creates a key store reader for the specified input file and password.
 586  
          * @param input the input file to read the pkcs12 data from.
 587  
          * @param pw the password for the pkcs12 file.
 588  
          * @return the key store reader requested, {@code null} if the key store cannot be read.
 589  
          * @since 0.3.0
 590  
          */
 591  
         protected KeyStoreReader createKeyStoreReader (
 592  
                 File input, char[] pw
 593  
         ) {
 594  
                 try {
 595  0
                         final InputStream is = new BufferedInputStream(new FileInputStream(input));
 596  
                         try {
 597  
                                 try {
 598  0
                                         return new KeyStoreReader(is, pw);
 599  0
                                 } catch (KeyStoreReaderException e) {
 600  0
                                         LOGGER.debug("Key store read error.", e);
 601  0
                                         showErrorDialog("readError", input.getAbsolutePath());
 602  
                                 }
 603  
                         } finally {
 604  0
                                 try {
 605  0
                                         is.close();
 606  0
                                 } catch (IOException e) {
 607  0
                                         LOGGER.debug("Error closing key store reader stream.", e);
 608  0
                                 }
 609  0
                         }
 610  0
                 } catch (FileNotFoundException e) {
 611  0
                         LOGGER.debug("File not found error.", e);
 612  0
                         showErrorDialog("fileNotFoundError", input.getAbsolutePath());
 613  0
                 }
 614  0
                 return null;
 615  
         }
 616  
 
 617  
         /**
 618  
          * Generates an attribute certificate for the specified key store reader and policy.
 619  
          * @param rd the key store reader to use for creation of the attribute certificate.
 620  
          * @param rolesAttribute the roles attribute.
 621  
          * @return the attribute certificate generated, {@code null} in case of an error.
 622  
          * @since 0.3.0
 623  
          */
 624  
         protected AttributeCertificate generateAttributeCertificate (
 625  
                 KeyStoreReader rd, Attribute rolesAttribute
 626  
         ) {
 627  
                 try {
 628  
                         // TODO Any The serial number used here should be generated.
 629  0
                         return new AttributeCertificateGenerator().
 630  
                                 reset().
 631  
                                 withSerialNumber(new BigInteger("1")).
 632  
                                 withIssuer(rd.getFirstX509Certificate(), rd.getFirstPrivateKey()).
 633  
                                 withHolder(new X500Principal(this.subject.getText())).
 634  
                                 withAttribute(rolesAttribute).
 635  
                                 notValidBefore(new Date(0L)).
 636  
                                 notValidAfter(new Date(Long.MAX_VALUE)).
 637  
                                 generate();
 638  0
                 } catch (Exception e) {
 639  0
                         LOGGER.debug("Generate error.", e);
 640  0
                         showErrorDialog("generateError", e.getMessage());
 641  
                 }
 642  0
                 return null;
 643  
         }
 644  
 
 645  
         /**
 646  
          * Encodes and writes an attribute certificate.
 647  
          * @param output the output file to write to.
 648  
          * @param ac the certificate to write.
 649  
          * @return {@code true} if the output file was written, {@code false} in case of an error.
 650  
          * @since 0.3.0
 651  
          */
 652  
         protected boolean writeAttributeCertificate (File output, AttributeCertificate ac) {
 653  
                 try {
 654  0
                         final BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(output));
 655  
                         try {
 656  
                                 try {
 657  0
                                         os.write(ac.getEncoded());
 658  0
                                         return true;
 659  0
                                 } catch (CertificateEncodingException e) {
 660  0
                                         LOGGER.debug("Certificate encoding error.", e);
 661  0
                                         showErrorDialog("encodeError", output.getAbsolutePath());
 662  0
                                 } catch (IOException e) {
 663  0
                                         LOGGER.debug("Certificate write error.", e);
 664  0
                                         showErrorDialog("writeFileError", output.getAbsolutePath());
 665  0
                                 }
 666  
                         } finally {
 667  0
                                 try {
 668  0
                                         os.close();
 669  0
                                 } catch (IOException e) {
 670  0
                                         LOGGER.debug("Certificate write error.", e);
 671  0
                                         showErrorDialog("writeFileError", output.getAbsolutePath());
 672  0
                                 }
 673  0
                         }
 674  0
                 } catch (FileNotFoundException e) {
 675  0
                         LOGGER.debug("Certificate write error.", e);
 676  0
                         showErrorDialog("createFileError", output.getAbsolutePath());
 677  0
                 }
 678  0
                 return false;
 679  
         }
 680  
 
 681  
         /**
 682  
          * Creates a an attribute certificate with the specified input pkcs12 file,
 683  
          * password and output file.
 684  
          * @param input the pkcs12 input file.
 685  
          * @param pw the password for the pkcs12 input file.
 686  
          * @param output the output file.
 687  
          * @return {@code true} if the attribute certificate was created, {@code false} otherwise.
 688  
          * @since 0.3.0
 689  
          */
 690  
         protected boolean createAttributeCertificate (File input, char[] pw, File output) {
 691  0
                 final KeyStoreReader rd = createKeyStoreReader(input, pw);
 692  0
                 if (rd == null) {
 693  0
                         return false;
 694  
                 }
 695  
                 
 696  0
                 final List<RoleDefinition> rolesDefs = new ArrayList<RoleDefinition>();
 697  0
                 if (this.selectedRoles.size() == 0) {
 698  0
                         showErrorDialog("noRolesError", "");
 699  0
                         return false;
 700  
                 }
 701  0
                 for (Role role : this.selectedRoles) {
 702  0
                         rolesDefs.add(
 703  
                                 new RoleAttribute.RoleDefinition(
 704  
                                         role.getRoleHierarchy().getIdentity().toString(),
 705  
                                         role.getName()
 706  
                                 )
 707  
                         );
 708  
                 }
 709  
                 
 710  0
                 final AttributeCertificate ac = generateAttributeCertificate(
 711  
                         rd,
 712  
                         new RoleAttribute(rolesDefs)
 713  
                 );
 714  0
                 if (ac == null) {
 715  0
                         return false;
 716  
                 }
 717  0
                 return writeAttributeCertificate(output, ac);
 718  
         }
 719  
 
 720  
         //---- Actions
 721  
 
 722  
         /**
 723  
          * Action to close the wizard without executing it.
 724  
          * @note Do not call directly, this action is triggered by the wizard.
 725  
          * @since 0.3.0
 726  
          */
 727  
         @Action
 728  
         public void cancel () {
 729  0
                 if (this.dialog != null) {
 730  0
                         this.dialog.dispose();
 731  
                 }
 732  0
         }
 733  
 
 734  
         /**
 735  
          * Action to execute the signing process.
 736  
          * @note Do not call directly, this action is triggered by the wizard.
 737  
          * @since 0.3.0
 738  
          */
 739  
         @Action
 740  
         public void execute () {
 741  0
                 final File input = new File(this.pkcs12File.getText());
 742  0
                 final char[] pw = this.password.getPassword();
 743  0
                 final File output = new File(this.aceFile.getText());
 744  0
                 if (
 745  
                         createAttributeCertificate(input, pw, output) &&
 746  
                         this.dialog != null
 747  
                 ) {
 748  0
                         this.dialog.dispose();
 749  
                 }
 750  0
         }
 751  
 
 752  
 }