Coverage Report - org.openpermis.editor.policy.view.PolicySigningWizard
 
Classes in this File Line Coverage Branch Coverage Complexity
PolicySigningWizard
0%
0/170
0%
0/30
2.24
PolicySigningWizard$1
0%
0/8
0%
0/2
2.24
PolicySigningWizard$2
0%
0/7
N/A
2.24
PolicySigningWizard$3
0%
0/3
N/A
2.24
PolicySigningWizard$4
0%
0/8
0%
0/4
2.24
PolicySigningWizard$5
0%
0/3
N/A
2.24
 
 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.io.StringWriter;
 34  
 import java.math.BigInteger;
 35  
 import java.security.cert.CertificateEncodingException;
 36  
 import java.util.Date;
 37  
 
 38  
 import javax.swing.ActionMap;
 39  
 import javax.swing.InputMap;
 40  
 import javax.swing.JButton;
 41  
 import javax.swing.JComponent;
 42  
 import javax.swing.JDialog;
 43  
 import javax.swing.JFileChooser;
 44  
 import javax.swing.JLabel;
 45  
 import javax.swing.JOptionPane;
 46  
 import javax.swing.JPanel;
 47  
 import javax.swing.JPasswordField;
 48  
 import javax.swing.JRootPane;
 49  
 import javax.swing.JTextField;
 50  
 import javax.swing.KeyStroke;
 51  
 import javax.swing.SwingConstants;
 52  
 import javax.swing.SwingUtilities;
 53  
 import javax.swing.UIManager;
 54  
 import javax.swing.border.Border;
 55  
 import javax.swing.border.EmptyBorder;
 56  
 import javax.swing.event.DocumentEvent;
 57  
 import javax.swing.event.DocumentListener;
 58  
 import javax.swing.text.JTextComponent;
 59  
 
 60  
 import org.jdesktop.application.Action;
 61  
 import org.jdesktop.application.ApplicationContext;
 62  
 import org.jdesktop.application.ResourceMap;
 63  
 import org.jdesktop.swingx.JXHeader;
 64  
 import org.jdesktop.swingx.JXHeader.IconPosition;
 65  
 import org.slf4j.Logger;
 66  
 import org.slf4j.LoggerFactory;
 67  
 
 68  
 import com.jgoodies.forms.factories.ComponentFactory;
 69  
 import com.jgoodies.forms.factories.DefaultComponentFactory;
 70  
 import com.jgoodies.forms.layout.FormLayout;
 71  
 
 72  
 import org.openpermis.cert.AttributeCertificate;
 73  
 import org.openpermis.cert.AttributeCertificateGenerator;
 74  
 import org.openpermis.cert.KeyStoreReader;
 75  
 import org.openpermis.cert.KeyStoreReaderException;
 76  
 import org.openpermis.cert.PolicyAttribute;
 77  
 import org.openpermis.editor.policy.Application;
 78  
 import org.openpermis.editor.policy.PolicyFileFilter;
 79  
 import org.openpermis.editor.policy.gui.SmartConstraints;
 80  
 import org.openpermis.policy.bean.PolicyBean;
 81  
 import org.openpermis.policy.io.PolicyException;
 82  
 import org.openpermis.policy.io.xml.PermisXmlWriter;
 83  
 
 84  
 /**
 85  
  * Wizard to sign policies.
 86  
  * @since 0.3.0
 87  
  */
 88  0
 public class PolicySigningWizard {
 89  
 
 90  
         //---- Static
 91  
 
 92  
         /**
 93  
          * The logger of this class.
 94  
          * @since 0.3.0
 95  
          */
 96  0
         private static final Logger LOGGER =
 97  
                 LoggerFactory.getLogger(PolicySigningWizard.class);
 98  
 
 99  
 
 100  
         /**
 101  
          * The number of columns in a text field.
 102  
          * @since 0.3.0
 103  
          */
 104  
         private static final int TEXT_FIELD_COLUMNS = 25;
 105  
 
 106  
         /**
 107  
          * Client property for chooser buttons that contains the next focus field.
 108  
          * @since 0.3.0
 109  
          */
 110  
         private static final String NEXT_FOCUS = "chooserNextFocus";
 111  
 
 112  
         /**
 113  
          * The text on the directory chooser buttons.
 114  
          * @since 0.3.0
 115  
          */
 116  
         private static final String CHOOSER_TEXT = "...";
 117  
 
 118  
         /**
 119  
          * The content border for the wizard.
 120  
          * @since 0.3.0
 121  
          */
 122  0
         private static final Border BORDER = new EmptyBorder(1, 0, 0, 1) {
 123  
                 private static final long serialVersionUID = 2189890664318454568L;
 124  
                 @Override
 125  0
                 public void paintBorder (Component c, Graphics g, int x, int y, int width, int height) {
 126  0
                         final Color color = g.getColor();
 127  0
                         final Color shadow = UIManager.getColor("Separator.shadow");
 128  0
                         g.setColor(shadow == null ? Color.GRAY : shadow);
 129  0
                         g.drawLine(x, y, x + width, y);
 130  0
                         g.drawLine(x, y + height - 1, x + width, y + height - 1);
 131  0
                         g.setColor(color);
 132  0
                 }
 133  
         };
 134  
 
 135  
         //---- State
 136  
 
 137  
         /**
 138  
          * The action map attached to this view instance.
 139  
          * @since 0.3.0
 140  
          */
 141  
         private final ActionMap actionMap;
 142  
 
 143  
         /**
 144  
          * The resource map attached to this view instance.
 145  
          * @since 0.3.0
 146  
          */
 147  
         private final ResourceMap resourceMap;
 148  
 
 149  
         /**
 150  
          * The string data of the policy to export to the ace file.
 151  
          * @since 0.3.0
 152  
          */
 153  
         private String policy;
 154  
 
 155  
         /**
 156  
          * The exception describing a policy problem if {@link #policy} is {@code null}.
 157  
          * @since 0.3.0
 158  
          */
 159  
         private PolicyException policyException;
 160  
 
 161  
         /**
 162  
          * Text field for the selection of the PKCS12 file.
 163  
          * @since 0.3.0
 164  
          */
 165  
         private final JTextField pkcs12File;
 166  
 
 167  
         /**
 168  
          * The wizard content pane.
 169  
          * @since 0.3.0
 170  
          */
 171  
         private final JPanel content;
 172  
 
 173  
         /**
 174  
          * Password field for the PKCS12 password.
 175  
          * @since 0.3.0
 176  
          */
 177  
         private final JPasswordField password;
 178  
 
 179  
         /**
 180  
          * Text field for the selection of the output file created.
 181  
          * @since 0.3.0
 182  
          */
 183  
         private final JTextField aceFile;
 184  
 
 185  
         /**
 186  
          * The default button of the wizard.
 187  
          * @since 0.3.0
 188  
          */
 189  
         private final JButton defaultButton;
 190  
 
 191  
         /**
 192  
          * The wizard dialog component.
 193  
          * @since 0.3.0
 194  
          */
 195  
         private JDialog dialog;
 196  
 
 197  
         //---- Constructors
 198  
 
 199  
         /**
 200  
          * Creates a wizard to sign policies.
 201  
          * @param context the application context used to lookup the action and resource map.
 202  
          * @param policy the policy to export to the ace file.
 203  
          * @since 0.3.0
 204  
          */
 205  0
         public PolicySigningWizard (ApplicationContext context, PolicyBean policy) {
 206  
                 try {
 207  0
                         this.policy = createPolicyString(policy);
 208  0
                         this.policyException = null;
 209  0
                 } catch (PolicyException e) {
 210  0
                         this.policy = null;
 211  0
                         this.policyException = e;
 212  0
                 }
 213  0
                 this.actionMap = context.getActionMap(getClass(), this);
 214  0
                 this.resourceMap = context.getResourceMap(getClass());
 215  0
                 this.content = new JPanel(new BorderLayout());
 216  0
                 final JXHeader header = new JXHeader(
 217  
                         this.resourceMap.getString("View.title"),
 218  
                         this.resourceMap.getString("View.description")
 219  
                 );
 220  0
                 header.setIcon(this.resourceMap.getIcon("View.icon"));
 221  0
                 header.setIconPosition(IconPosition.LEFT);
 222  0
                 this.content.add(header, BorderLayout.PAGE_START);
 223  0
                 final FormLayout layout = new FormLayout(
 224  
                         "4dlu, pref, 4dlu, pref:grow, pref, 4dlu",
 225  
                         "8dlu, pref, 4dlu, pref, 2dlu, pref, 4dlu, pref, 4dlu, pref, 8dlu, pref:grow"
 226  
                 );
 227  0
                 final JPanel wizard = new JPanel(layout);
 228  0
                 wizard.setBorder(BORDER);
 229  0
                 final SmartConstraints cc = new SmartConstraints(2, 2);
 230  0
                 wizard.add(createSeparator("input"), cc.yw(2, layout.getColumnCount() - 2));
 231  0
                 final JLabel pkcs12FileLabel = createLabel("pkcs12File");
 232  0
                 wizard.add(pkcs12FileLabel, cc.x(2));
 233  0
                 this.pkcs12File = createTextField(pkcs12FileLabel);
 234  0
                 wizard.add(this.pkcs12File, cc.x(1));
 235  0
                 final JButton pkcs12FileChooser =
 236  
                         createChooser(this.pkcs12File, JFileChooser.OPEN_DIALOG, null);
 237  0
                 wizard.add(pkcs12FileChooser, cc.y(2));
 238  0
                 final JLabel passwordLabel = createLabel("password");
 239  0
                 wizard.add(passwordLabel, cc.x(2));
 240  0
                 this.password = createPasswordField(passwordLabel);
 241  0
                 pkcs12FileChooser.putClientProperty(NEXT_FOCUS, this.password);
 242  0
                 wizard.add(this.password, cc.y(2));
 243  0
                 wizard.add(createSeparator("output"), cc.yw(2, layout.getColumnCount() - 2));
 244  0
                 final JLabel aceFileLabel = createLabel("aceFile");
 245  0
                 wizard.add(aceFileLabel, cc.x(2));
 246  0
                 this.aceFile = createTextField(aceFileLabel);
 247  0
                 wizard.add(this.aceFile, cc.x(1));
 248  0
                 final JButton aceFileChooser =
 249  
                         createChooser(this.aceFile, JFileChooser.SAVE_DIALOG, PolicyFileFilter.ACE_FILE_FILTER);
 250  0
                 wizard.add(aceFileChooser, cc.y(2));
 251  0
                 this.content.add(wizard, BorderLayout.CENTER);
 252  0
                 final JPanel buttons = new JPanel(
 253  
                         new FormLayout(
 254  
                                 "4dlu:grow, pref, 2dlu, pref, 4dlu",
 255  
                                 "4dlu, pref, 4dlu"
 256  
                         )
 257  
                 );
 258  0
                 cc.reset(2, 2);
 259  0
                 buttons.add(new JButton(this.actionMap.get("cancel")), cc.x(2));
 260  0
                 this.defaultButton = new JButton(this.actionMap.get("execute"));
 261  0
                 aceFileChooser.putClientProperty(NEXT_FOCUS, this.defaultButton);
 262  0
                 buttons.add(this.defaultButton, cc.y(1));
 263  0
                 this.content.add(buttons, BorderLayout.PAGE_END);
 264  0
                 this.resourceMap.injectComponents(this.content);
 265  0
         }
 266  
 
 267  
         //---- Methods
 268  
 
 269  
         /**
 270  
          * Updates the actions according to the values in the wizard fields.
 271  
          * @since 0.3.0
 272  
          */
 273  
         private final void updateActions () {
 274  0
                 final boolean validPkcs12File = new File(this.pkcs12File.getText()).isFile();
 275  0
                 final File aceParentFile = new File(this.aceFile.getText()).getParentFile();
 276  0
                 final boolean validAceFile = aceParentFile != null && aceParentFile.isDirectory();
 277  0
                 this.actionMap.get("execute").setEnabled(validPkcs12File && validAceFile);
 278  0
         }
 279  
 
 280  
         /**
 281  
          * Configures the specified text component.
 282  
          * <p>Changes to the document of the text component will cause the actions of the wizard
 283  
          * to be updated (see {@link #updateActions()}. In addition a label for the text field
 284  
          * is configured.</p>
 285  
          * @param <T> the type of text component to configure.
 286  
          * @param component the text component to configure.
 287  
          * @param label the label of the text component, must not be {@code null}.
 288  
          * @return the text component passed in for fluent use.
 289  
          * @since 0.3.0
 290  
          */
 291  
         private final <T extends JTextComponent> T configure (T component, JLabel label) {
 292  0
                 component.getDocument().addDocumentListener(
 293  
                         new DocumentListener() {
 294  
                                 public void changedUpdate (DocumentEvent e) {
 295  0
                                         updateActions();
 296  0
                                 }
 297  
                                 public void insertUpdate (DocumentEvent e) {
 298  0
                                         updateActions();
 299  0
                                 }
 300  0
                                 public void removeUpdate (DocumentEvent e) {
 301  0
                                         updateActions();
 302  0
                                 }
 303  
                         }
 304  
                 );
 305  0
                 label.setLabelFor(component);
 306  0
                 return component;
 307  
         }
 308  
 
 309  
         /**
 310  
          * Creates a named separator for automated translation.
 311  
          * @param name the name of the separator.
 312  
          * @return the separator created.
 313  
          * @since 0.3.0
 314  
          */
 315  
         private final JComponent createSeparator (String name) {
 316  0
                 final ComponentFactory factory = DefaultComponentFactory.getInstance();
 317  0
                 final JComponent separator = factory.createSeparator(name, SwingConstants.LEFT);
 318  0
                 for (Component child : separator.getComponents()) {
 319  0
                         if (child instanceof JLabel) {
 320  0
                                 ((JLabel) child).setName(name);
 321  
                         }
 322  
                 }
 323  0
                 return separator;
 324  
         }
 325  
 
 326  
         /**
 327  
          * Creates a named label for automated translation.
 328  
          * @param name the name of the label.
 329  
          * @return the label created.
 330  
          * @since 0.3.0
 331  
          */
 332  
         private final JLabel createLabel (String name) {
 333  0
                 final JLabel label = new JLabel(name);
 334  0
                 label.setName(name);
 335  0
                 return label;
 336  
         }
 337  
 
 338  
         /**
 339  
          * Creates and configures a text field.
 340  
          * @param label the label of the text field.
 341  
          * @return the text field created.
 342  
          * @since 0.3.0
 343  
          */
 344  
         private final JTextField createTextField (JLabel label) {
 345  0
                 final JTextField textField = configure(new JTextField(TEXT_FIELD_COLUMNS), label);
 346  0
                 textField.setEditable(false);
 347  0
                 return textField;
 348  
         }
 349  
 
 350  
         /**
 351  
          * Creates and configures a password field.
 352  
          * @param label the label of the password field.
 353  
          * @return the password field created.
 354  
          * @since 0.3.0
 355  
          */
 356  
         private final JPasswordField createPasswordField (JLabel label) {
 357  0
                 return configure(new JPasswordField(TEXT_FIELD_COLUMNS), label);
 358  
         }
 359  
 
 360  
         /**
 361  
          * Creates a file chooser button for the specified target field.
 362  
          * @param target the field to store the chosen file to.
 363  
          * @param type the file chooser type, either {@link JFileChooser#OPEN_DIALOG} or
 364  
          * {@link JFileChooser#SAVE_DIALOG}.
 365  
          * @param filter the file filter to use.
 366  
          * @return the button created.
 367  
          * @since 0.3.0
 368  
          */
 369  
         private final JButton createChooser (
 370  
                 final JTextField target, final int type, final PolicyFileFilter filter
 371  
         ) {
 372  0
                 final JButton chooser = new JButton(CHOOSER_TEXT) {
 373  
                         private static final long serialVersionUID = -3525515562208051410L;
 374  
                         @Override
 375  0
                         public Dimension getPreferredSize () {
 376  0
                                 final Dimension size = super.getPreferredSize();
 377  0
                                 return new Dimension(size.width, target.getPreferredSize().height);
 378  
                         }
 379  
                 };
 380  0
                 chooser.addActionListener(
 381  
                         new ActionListener() {
 382  0
                                 public void actionPerformed (ActionEvent e) {
 383  0
                                         final File file = Application.getInstance().chooseFile(type, false, filter);
 384  0
                                         if (file != null) {
 385  0
                                                 target.setText(file.getAbsolutePath());
 386  0
                                                 final JComponent focus = (JComponent) chooser.getClientProperty(NEXT_FOCUS);
 387  0
                                                 if (focus != null) {
 388  0
                                                         focus.requestFocusInWindow();
 389  
                                                 }
 390  
                                         }
 391  0
                                 }
 392  
                         }
 393  
                 );
 394  0
                 return chooser;
 395  
         }
 396  
 
 397  
         /**
 398  
          * Shows an error dialog with the specified title, message and paramters.
 399  
          * @param key translation key for the title.
 400  
          * @param args optional parameters for the title and message.
 401  
          * @since 0.3.0
 402  
          */
 403  
         protected void showErrorDialog (String key, Object... args) {
 404  0
                 showErrorDialog(this.dialog, key, args);
 405  0
         }
 406  
 
 407  
         /**
 408  
          * Shows an error dialog with the specified title, message and paramters.
 409  
          * @param parent the parent component to show the error dialog for.
 410  
          * @param key translation key for the title.
 411  
          * @param args optional parameters for the title and message.
 412  
          * @since 0.3.0
 413  
          */
 414  
         protected void showErrorDialog (Component parent, String key, Object... args) {
 415  0
                 JOptionPane.showMessageDialog(
 416  
                         parent,
 417  
                         this.resourceMap.getString(key + ".message", args),
 418  
                         this.resourceMap.getString(key + ".title", args),
 419  
                         JOptionPane.ERROR_MESSAGE
 420  
                 );
 421  0
         }
 422  
 
 423  
         /**
 424  
          * Starts the wizard.
 425  
          * @param parent the parent component of the dialog.
 426  
          * @since 0.3.0
 427  
          */
 428  
         public void show (Component parent) {
 429  0
                 if (this.policyException != null) {
 430  0
                         showErrorDialog(parent, "policyError", this.policyException.getMessage());
 431  0
                         return;
 432  
                 }
 433  0
                 this.pkcs12File.setText("");
 434  0
                 this.password.setText("");
 435  0
                 this.aceFile.setText("");
 436  0
                 updateActions();
 437  0
                 final Window window = parent == null ? null : SwingUtilities.getWindowAncestor(parent);
 438  0
                 final String title = this.resourceMap.getString("View.title");
 439  0
                 if (window instanceof Frame) {
 440  0
                         this.dialog = new JDialog((Frame) window, title, true);
 441  0
                 } else if (window instanceof Dialog) {
 442  0
                         this.dialog = new JDialog((Dialog) window, title, true);
 443  
                 } else {
 444  0
                         this.dialog = new JDialog((Frame) null, title, true);
 445  
                 }
 446  0
                 final JRootPane root = this.dialog.getRootPane();
 447  0
                 final KeyStroke enterKey = KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0, false);
 448  0
                 final KeyStroke escapeKey = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false);
 449  0
                 final InputMap focusAncestorInputMap =
 450  
                         root.getInputMap(JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);
 451  0
                 focusAncestorInputMap.put(enterKey, "execute");
 452  0
                 focusAncestorInputMap.put(escapeKey, "cancel");
 453  0
                 root.getActionMap().put("execute", this.actionMap.get("execute"));
 454  0
                 root.getActionMap().put("cancel", this.actionMap.get("cancel"));
 455  0
                 root.setDefaultButton(this.defaultButton);
 456  0
                 this.dialog.setDefaultCloseOperation(JDialog.DO_NOTHING_ON_CLOSE);
 457  0
                 this.dialog.addWindowListener(
 458  
                         new WindowAdapter() {
 459  
                                 @Override
 460  0
                                 public void windowClosing (WindowEvent e) {
 461  0
                                         PolicySigningWizard.this.actionMap.get("cancel").actionPerformed(null);
 462  0
                                 }
 463  
                         }
 464  
                 );
 465  0
                 this.dialog.setContentPane(this.content);
 466  0
                 this.dialog.pack();
 467  0
                 this.dialog.setLocationRelativeTo(parent);
 468  0
                 this.dialog.setVisible(true);
 469  0
         }
 470  
 
 471  
         /**
 472  
          * Creates a key store reader for the specified input file and password.
 473  
          * @param input the input file to read the pkcs12 data from.
 474  
          * @param pw the password for the pkcs12 file.
 475  
          * @return the key store reader requested, {@code null} if the key store cannot be read.
 476  
          * @since 0.3.0
 477  
          */
 478  
         protected KeyStoreReader createKeyStoreReader (
 479  
                 File input, char[] pw
 480  
         ) {
 481  
                 try {
 482  0
                         final InputStream is = new BufferedInputStream(new FileInputStream(input));
 483  
                         try {
 484  
                                 try {
 485  0
                                         return new KeyStoreReader(is, pw);
 486  0
                                 } catch (KeyStoreReaderException e) {
 487  0
                                         LOGGER.debug("Key store read error.", e);
 488  0
                                         showErrorDialog("readError", input.getAbsolutePath());
 489  
                                 }
 490  
                         } finally {
 491  0
                                 try {
 492  0
                                         is.close();
 493  0
                                 } catch (IOException e) {
 494  0
                                         LOGGER.debug("Error closing key store reader stream.", e);
 495  0
                                 }
 496  0
                         }
 497  0
                 } catch (FileNotFoundException e) {
 498  0
                         LOGGER.debug("File not found error.", e);
 499  0
                         showErrorDialog("fileNotFoundError", input.getAbsolutePath());
 500  0
                 }
 501  0
                 return null;
 502  
         }
 503  
 
 504  
         /**
 505  
          * Generates an attribute certificate for the specified key store reader and policy.
 506  
          * @param rd the key store reader to use for creation of the attribute certificate.
 507  
          * @param policyString the policy as string data to write.
 508  
          * @return the attribute certificate generated, {@code null} in case of an error.
 509  
          * @since 0.3.0
 510  
          */
 511  
         protected AttributeCertificate generateAttributeCertificate (
 512  
                 KeyStoreReader rd, String policyString
 513  
         ) {
 514  
                 try {
 515  
                         // TODO Any The serial number used here should be generated.
 516  0
                         return new AttributeCertificateGenerator().
 517  
                                 reset().
 518  
                                 withSerialNumber(new BigInteger("1")).
 519  
                                 withIssuer(rd.getFirstX509Certificate(), rd.getFirstPrivateKey()).
 520  
                                 withHolder(rd.getFirstX509Certificate().getSubjectX500Principal()).
 521  
                                 withAttribute(new PolicyAttribute(policyString)).
 522  
                                 notValidBefore(new Date(0L)).
 523  
                                 notValidAfter(new Date(Long.MAX_VALUE)).
 524  
                                 generate();
 525  0
                 } catch (Exception e) {
 526  0
                         LOGGER.debug("Generate error.", e);
 527  0
                         showErrorDialog("generateError", e.getMessage());
 528  
                 }
 529  0
                 return null;
 530  
         }
 531  
 
 532  
         /**
 533  
          * Creates a string representation of the policy of this wizard.
 534  
          * @param policyBean the policy to create the string representation for.
 535  
          * @return the string requested, {@code null} in case of an error.
 536  
          * @throws PolicyException passed on.
 537  
          * @since 0.3.0
 538  
          */
 539  
         protected String createPolicyString (PolicyBean policyBean) throws PolicyException {
 540  0
                 final StringWriter wr = new StringWriter();
 541  0
                 new PermisXmlWriter(wr).writePolicy(policyBean);
 542  0
                 return wr.toString();
 543  
         }
 544  
 
 545  
         /**
 546  
          * Encodes and writes an attribute certificate.
 547  
          * @param output the output file to write to.
 548  
          * @param ac the certificate to write.
 549  
          * @return {@code true} if the output file was written, {@code false} in case of an error.
 550  
          * @since 0.3.0
 551  
          */
 552  
         protected boolean writeAttributeCertificate (File output, AttributeCertificate ac) {
 553  
                 try {
 554  0
                         final BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream(output));
 555  
                         try {
 556  
                                 try {
 557  0
                                         os.write(ac.getEncoded());
 558  0
                                         return true;
 559  0
                                 } catch (CertificateEncodingException e) {
 560  0
                                         LOGGER.debug("Certificate encoding error.", e);
 561  0
                                         showErrorDialog("encodeError", output.getAbsolutePath());
 562  0
                                 } catch (IOException e) {
 563  0
                                         LOGGER.debug("Certificate write error.", e);
 564  0
                                         showErrorDialog("writeFileError", output.getAbsolutePath());
 565  0
                                 }
 566  
                         } finally {
 567  0
                                 try {
 568  0
                                         os.close();
 569  0
                                 } catch (IOException e) {
 570  0
                                         LOGGER.debug("Certificate write error.", e);
 571  0
                                         showErrorDialog("writeFileError", output.getAbsolutePath());
 572  0
                                 }
 573  0
                         }
 574  0
                 } catch (FileNotFoundException e) {
 575  0
                         LOGGER.debug("Certificate write error.", e);
 576  0
                         showErrorDialog("createFileError", output.getAbsolutePath());
 577  0
                 }
 578  0
                 return false;
 579  
         }
 580  
 
 581  
         /**
 582  
          * Creates a signed policy with the specified input pkcs12 file, password and output file.
 583  
          * @param input the pkcs12 input file.
 584  
          * @param pw the password for the pkcs12 input file.
 585  
          * @param output the output file.
 586  
          * @return {@code true} if the signed policy was created, {@code false} otherwise.
 587  
          * @since 0.3.0
 588  
          */
 589  
         protected boolean createSignedPolicy (File input, char[] pw, File output) {
 590  0
                 final KeyStoreReader rd = createKeyStoreReader(input, pw);
 591  0
                 if (rd == null) {
 592  0
                         return false;
 593  
                 }
 594  0
                 final AttributeCertificate ac = generateAttributeCertificate(rd, this.policy);
 595  0
                 if (ac == null) {
 596  0
                         return false;
 597  
                 }
 598  0
                 return writeAttributeCertificate(output, ac);
 599  
         }
 600  
 
 601  
         //---- Actions
 602  
 
 603  
         /**
 604  
          * Action to close the wizard without executing it.
 605  
          * @note Do not call directly, this action is triggered by the wizard.
 606  
          * @since 0.3.0
 607  
          */
 608  
         @Action
 609  
         public void cancel () {
 610  0
                 if (this.dialog != null) {
 611  0
                         this.dialog.dispose();
 612  
                 }
 613  0
         }
 614  
 
 615  
         /**
 616  
          * Action to execute the signing process.
 617  
          * @note Do not call directly, this action is triggered by the wizard.
 618  
          * @since 0.3.0
 619  
          */
 620  
         @Action
 621  
         public void execute () {
 622  0
                 final File input = new File(this.pkcs12File.getText());
 623  0
                 final char[] pw = this.password.getPassword();
 624  0
                 final File output = new File(this.aceFile.getText());
 625  0
                 if (
 626  
                         createSignedPolicy(input, pw, output) &&
 627  
                         this.dialog != null
 628  
                 ) {
 629  0
                         this.dialog.dispose();
 630  
                 }
 631  0
         }
 632  
 
 633  
 }