diff options
| author | clemenso <clemenso@8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4> | 2009-02-26 19:39:00 +0000 | 
|---|---|---|
| committer | clemenso <clemenso@8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4> | 2009-02-26 19:39:00 +0000 | 
| commit | 6576428966f1e3d688269a407b072fb01f9f7647 (patch) | |
| tree | f79a9c3c70c27477133c9283dd4b0440b7559d05 | |
| parent | bd18d9084fd139aaae40ad8d525c1d0e626f2e5e (diff) | |
| download | mocca-6576428966f1e3d688269a407b072fb01f9f7647.tar.gz mocca-6576428966f1e3d688269a407b072fb01f9f7647.tar.bz2 mocca-6576428966f1e3d688269a407b072fb01f9f7647.zip | |
1.1 candidate (activation)
git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@309 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4
41 files changed, 3711 insertions, 2197 deletions
| diff --git a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java index 5a57ef18..8c1bd2bd 100644 --- a/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java +++ b/BKUApplet/src/main/java/at/gv/egiz/bku/online/applet/AppletBKUWorker.java @@ -195,11 +195,16 @@ public class AppletBKUWorker extends AbstractBKUWorker implements Runnable {      }    } +  /** +   * +   * @param err_code +   * @param ex if not null, the message will be appended as parameter to the error message +   */    protected void showErrorDialog(String err_code, Exception ex) {      actionCommandList.clear();      actionCommandList.add("ok"); -    gui.showErrorDialog(err_code, -            new Object[]{ex.getMessage()}, this, "ok"); +    Object[] params = (ex != null) ? new Object[] { ex.getMessage() } : null; +    gui.showErrorDialog(err_code, params, this, "ok");      try {        waitForAction();      } catch (InterruptedException e) { diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java index 8acf051e..8eef8aea 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUI.java @@ -17,15 +17,28 @@  package at.gv.egiz.bku.gui; +import at.gv.egiz.smcc.PINSpec;  import java.awt.Container; +import java.awt.Cursor; +import java.awt.event.ActionEvent;  import java.awt.event.ActionListener; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionAdapter;  import java.net.URL; +import java.text.MessageFormat;  import java.util.Locale; +import java.util.Map;  import javax.swing.GroupLayout;  import javax.swing.JButton;  import javax.swing.JLabel; +import javax.swing.JPasswordField; +import javax.swing.JScrollPane; +import javax.swing.JTable;  import javax.swing.LayoutStyle; +import javax.swing.ListSelectionModel;  import javax.swing.SwingUtilities; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener;  /**   * TODO pull out ResourceBundle to common superclass for activationGUI and pinMgmtGUI @@ -33,9 +46,10 @@ import javax.swing.SwingUtilities;   */  public class PINManagementGUI extends ActivationGUI implements PINManagementGUIFacade { -  public static final String BUTTON_ACTIVATE = "button.activate"; -  public static final String BUTTON_UNBLOCK = "button.unblock"; -  public static final String BUTTON_CHANGE = "button.change"; +  /** remember the pinfield to return to worker */ +  protected JPasswordField oldPinField; +  /** remember the pinSpec to return to worker */ +  protected PINSpec pinSpec;    public PINManagementGUI(Container contentPane,            Locale locale, @@ -46,12 +60,31 @@ public class PINManagementGUI extends ActivationGUI implements PINManagementGUIF    }    @Override -  public void showPINManagementDialog(final PINStatusProvider pinStatusProvider, -          final ActionListener activateListener, final String activateCmd, -          final ActionListener changeListener, final String changeCmd, -          final ActionListener unblockListener, final String unblockCmd, -          final ActionListener cancelListener, final String cancelCmd) { -//    try { +  public char[] getOldPin() { +    if (oldPinField != null) { +      char[] pin = oldPinField.getPassword(); +      oldPinField = null; +      return pin; +    } +    return null; +  } + +  @Override +  public PINSpec getSelectedPIN() { +    return pinSpec; +  } + +  @Override +  public void showPINManagementDialog(final Map<PINSpec, STATUS> pins,  +          final ActionListener activateListener, +          final String activateCmd, +          final String changeCmd, +          final String unblockCmd, +          final ActionListener cancelListener, +          final String cancelCmd) { + +      log.debug("scheduling PIN managment dialog"); +            SwingUtilities.invokeLater(new Runnable() {          @Override @@ -68,13 +101,76 @@ public class PINManagementGUI extends ActivationGUI implements PINManagementGUIF                  if (renderHeaderPanel) {                    titleLabel.setText(cardmgmtMessages.getString(TITLE_PINMGMT)); -                  mgmtLabel.setText(cardmgmtMessages.getString(MESSAGE_PINMGMT)); +                  String infoPattern = cardmgmtMessages.getString(MESSAGE_PINMGMT); +                  mgmtLabel.setText(MessageFormat.format(infoPattern, pins.size()));                  } else {                    mgmtLabel.setText(cardmgmtMessages.getString(TITLE_PINMGMT));                  } +                final PINStatusTableModel tableModel = new PINStatusTableModel(pins); +                final JTable pinStatusTable = new JTable(tableModel); +                pinStatusTable.setDefaultRenderer(PINSpec.class, new PINSpecRenderer()); +                pinStatusTable.setDefaultRenderer(STATUS.class, new PINStatusRenderer(cardmgmtMessages)); +                pinStatusTable.setTableHeader(null); -                 +                pinStatusTable.addMouseMotionListener(new MouseMotionAdapter() { + +                  @Override +                  public void mouseMoved(MouseEvent e) { +                    if (pinStatusTable.columnAtPoint(e.getPoint()) == 0) { +                      pinStatusTable.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); +                    } else { +                      pinStatusTable.setCursor(Cursor.getDefaultCursor()); +                    } +                  } +                }); + +                final JButton activateButton = new JButton(); +                activateButton.setFont(activateButton.getFont().deriveFont(activateButton.getFont().getStyle() & ~java.awt.Font.BOLD)); +                activateButton.addActionListener(activateListener); + +                pinStatusTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); +                pinStatusTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { + +                  @Override +                  public void valueChanged(final ListSelectionEvent e) { +                    //invoke later to allow thread to paint selection background +                    SwingUtilities.invokeLater(new Runnable() { + +                      @Override +                      public void run() { +                        ListSelectionModel lsm = (ListSelectionModel) e.getSource(); +                        int selectionIdx = lsm.getMinSelectionIndex(); +                        if (selectionIdx >= 0) { +                          pinSpec = (PINSpec) tableModel.getValueAt(selectionIdx, 0); +                          STATUS status = (STATUS) tableModel.getValueAt(selectionIdx, 1); + +                          if (status == STATUS.NOT_ACTIV) { +                            activateButton.setText(cardmgmtMessages.getString(BUTTON_ACTIVATE)); +                            activateButton.setEnabled(true); +                            activateButton.setActionCommand(activateCmd); +                          } else if (status == STATUS.BLOCKED) { +                            activateButton.setText(cardmgmtMessages.getString(BUTTON_UNBLOCK)); +                            activateButton.setEnabled(true); +                            activateButton.setActionCommand(unblockCmd); +                          } else if (status == STATUS.ACTIV) { +                            activateButton.setText(cardmgmtMessages.getString(BUTTON_CHANGE)); +                            activateButton.setEnabled(true); +                            activateButton.setActionCommand(changeCmd); +                          } else { +                            activateButton.setText(cardmgmtMessages.getString(BUTTON_ACTIVATE)); +                            activateButton.setEnabled(false); +                          } +                        } +                      } +                    }); +                  } +                }); + +                //select first entry +                pinStatusTable.getSelectionModel().setSelectionInterval(0, 0); + +                JScrollPane pinStatusScrollPane = new JScrollPane(pinStatusTable);                  GroupLayout mainPanelLayout = new GroupLayout(mainPanel);                  mainPanel.setLayout(mainPanelLayout); @@ -91,30 +187,16 @@ public class PINManagementGUI extends ActivationGUI implements PINManagementGUIF                            .addComponent(helpLabel);                  } -                mainPanelLayout.setHorizontalGroup(messageHorizontal); -                mainPanelLayout.setVerticalGroup(messageVertical); +                mainPanelLayout.setHorizontalGroup( +                mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) +                  .addGroup(messageHorizontal) +                  .addComponent(pinStatusScrollPane, 0, 0, Short.MAX_VALUE)); - -                JButton activateButton = new JButton(); -                activateButton.setFont(activateButton.getFont().deriveFont(activateButton.getFont().getStyle() & ~java.awt.Font.BOLD)); -                activateButton.setText(cardmgmtMessages.getString(BUTTON_ACTIVATE)); -                activateButton.setEnabled(true);//false); -                activateButton.setActionCommand(activateCmd); -                activateButton.addActionListener(activateListener); - -                JButton changeButton = new JButton(); -                changeButton.setFont(activateButton.getFont().deriveFont(activateButton.getFont().getStyle() & ~java.awt.Font.BOLD)); -                changeButton.setText(cardmgmtMessages.getString(BUTTON_CHANGE)); -                changeButton.setEnabled(false); -                changeButton.setActionCommand(changeCmd); -                changeButton.addActionListener(changeListener); - -                JButton unblockButton = new JButton(); -                unblockButton.setFont(activateButton.getFont().deriveFont(activateButton.getFont().getStyle() & ~java.awt.Font.BOLD)); -                unblockButton.setText(cardmgmtMessages.getString(BUTTON_UNBLOCK)); -                unblockButton.setEnabled(false); -                unblockButton.setActionCommand(unblockCmd); -                unblockButton.addActionListener(unblockListener); +                mainPanelLayout.setVerticalGroup( +                  mainPanelLayout.createSequentialGroup() +                    .addGroup(messageVertical) +                    .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +                    .addComponent(pinStatusScrollPane, 0, 0, pinStatusTable.getPreferredSize().height+3));                  JButton cancelButton = new JButton();                  cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); @@ -129,30 +211,377 @@ public class PINManagementGUI extends ActivationGUI implements PINManagementGUIF                          .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)                          .addComponent(activateButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)                          .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) -                        .addComponent(changeButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) -                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) -                        .addComponent(unblockButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE) -                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)                          .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE);                  GroupLayout.Group buttonVertical = buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE)                            .addComponent(activateButton) -                          .addComponent(changeButton) -                          .addComponent(unblockButton)                            .addComponent(cancelButton);                  buttonPanelLayout.setHorizontalGroup(buttonHorizontal);                  buttonPanelLayout.setVerticalGroup(buttonVertical);                  contentPanel.validate(); -          }        }); +  } + +  @Override +  public void showActivatePINDialog(final PINSpec pin, +          final ActionListener okListener, final String okCommand, +          final ActionListener cancelListener, final String cancelCommand) { +    log.debug("scheduling activate pin dialog"); +    showPINDialog(false, pin, okListener, okCommand, cancelListener, cancelCommand); +  } + + +  private void showPINDialog(final boolean changePin, final PINSpec pinSpec, +          final ActionListener okListener, final String okCommand, +          final ActionListener cancelListener, final String cancelCommand) { + +      SwingUtilities.invokeLater(new Runnable() { + +            @Override +            public void run() { + +              String HELP_TOPIC, TITLE, MESSAGE_MGMT; +              if (changePin) { +                log.debug("show change pin dialog"); +                HELP_TOPIC = HELP_PINMGMT; +                TITLE = TITLE_CHANGE_PIN; +                MESSAGE_MGMT = MESSAGE_CHANGE_PIN; +              } else { +                log.debug("show activate pin dialog"); +                HELP_TOPIC = HELP_PINMGMT; +                TITLE = TITLE_ACTIVATE_PIN; +                MESSAGE_MGMT = MESSAGE_ACTIVATE_PIN; +                oldPinField = null; +              } + +                mainPanel.removeAll(); +                buttonPanel.removeAll(); + +                helpListener.setHelpTopic(HELP_TOPIC); + +                JLabel mgmtLabel = new JLabel(); +                mgmtLabel.setFont(mgmtLabel.getFont().deriveFont(mgmtLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); + +                if (renderHeaderPanel) { +                  titleLabel.setText(cardmgmtMessages.getString(TITLE)); +                  String mgmtPattern = cardmgmtMessages.getString(MESSAGE_MGMT); +                  if (shortText) { +                    mgmtLabel.setText(MessageFormat.format(mgmtPattern, "PIN")); +                  } else { +                    mgmtLabel.setText(MessageFormat.format(mgmtPattern, pinSpec.getLocalizedName())); +                  } +                } else { +                  mgmtLabel.setText(cardmgmtMessages.getString(TITLE)); +                } + +                JButton okButton = new JButton(); +                okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~java.awt.Font.BOLD)); +                okButton.setText(messages.getString(BUTTON_OK)); +                okButton.setEnabled(false); +                okButton.setActionCommand(okCommand); +                okButton.addActionListener(okListener); + +                JLabel pinLabel = new JLabel(); +                pinLabel.setFont(pinLabel.getFont().deriveFont(pinLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); +                String pinLabelPattern = (changePin) ? cardmgmtMessages.getString(LABEL_NEW_PIN) : messages.getString(LABEL_PIN); +                pinLabel.setText(MessageFormat.format(pinLabelPattern, new Object[]{pinSpec.getLocalizedName()})); + +                final JPasswordField repeatPinField = new JPasswordField(); +                pinField = new JPasswordField(); +                pinField.setText(""); +                pinField.setDocument(new PINDocument(pinSpec, null)); +                pinField.setActionCommand(okCommand); +                pinField.addActionListener(new ActionListener() { + +                    @Override +                    public void actionPerformed(ActionEvent e) { +                        if (pinField.getPassword().length >= pinSpec.getMinLength()) { +                          repeatPinField.requestFocusInWindow(); +                        } +                    } +                }); +                JLabel repeatPinLabel = new JLabel(); +                repeatPinLabel.setFont(pinLabel.getFont()); +                String repeatPinLabelPattern = cardmgmtMessages.getString(LABEL_REPEAT_PIN); +                repeatPinLabel.setText(MessageFormat.format(repeatPinLabelPattern, new Object[]{pinSpec.getLocalizedName()})); + +                repeatPinField.setText(""); +                repeatPinField.setDocument(new PINDocument(pinSpec, okButton, pinField.getDocument())); +                repeatPinField.setActionCommand(okCommand); +                repeatPinField.addActionListener(new ActionListener() { + +                    @Override +                    public void actionPerformed(ActionEvent e) { +                        if (pinField.getPassword().length >= pinSpec.getMinLength()) { +                            okListener.actionPerformed(e); +                        } +                    } +                }); + +                JLabel oldPinLabel = null; +                if (changePin) { +                  oldPinLabel = new JLabel(); +                  oldPinLabel.setFont(oldPinLabel.getFont().deriveFont(oldPinLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); +                  String oldPinLabelPattern = cardmgmtMessages.getString(LABEL_OLD_PIN); +                  oldPinLabel.setText(MessageFormat.format(oldPinLabelPattern, new Object[]{pinSpec.getLocalizedName()})); + +                  oldPinField = new JPasswordField(); +                  oldPinField.setText(""); +                  oldPinField.setDocument(new PINDocument(pinSpec, null)); +                  oldPinField.setActionCommand(okCommand); +                  oldPinField.addActionListener(new ActionListener() { + +                      @Override +                      public void actionPerformed(ActionEvent e) { +                          if (oldPinField.getPassword().length >= pinSpec.getMinLength()) { +                            pinField.requestFocusInWindow(); +                          } +                      } +                  }); +                } +                 +                JLabel pinsizeLabel = new JLabel(); +                pinsizeLabel.setFont(pinsizeLabel.getFont().deriveFont(pinsizeLabel.getFont().getStyle() & ~java.awt.Font.BOLD, pinsizeLabel.getFont().getSize()-2)); +                String pinsizePattern = messages.getString(LABEL_PINSIZE); +                String pinSize = String.valueOf(pinSpec.getMinLength()); +                if (pinSpec.getMinLength() != pinSpec.getMaxLength()) { +                    pinSize += "-" + pinSpec.getMaxLength(); +                } +                pinsizeLabel.setText(MessageFormat.format(pinsizePattern, new Object[]{pinSize})); + +                GroupLayout mainPanelLayout = new GroupLayout(mainPanel); +                mainPanel.setLayout(mainPanelLayout); + +                GroupLayout.SequentialGroup infoHorizontal = mainPanelLayout.createSequentialGroup() +                          .addComponent(mgmtLabel); +                GroupLayout.ParallelGroup infoVertical = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) +                          .addComponent(mgmtLabel); + +                if (!renderHeaderPanel) { +                  infoHorizontal +                          .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) +                          .addComponent(helpLabel); +                  infoVertical +                          .addComponent(helpLabel); +                } -//    } catch (Exception ex) { -//      log.error(ex.getMessage(), ex); -//      showErrorDialog(ERR_UNKNOWN_WITH_PARAM, new Object[] {ex.getMessage()}); -//    } +                GroupLayout.ParallelGroup pinHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); +                GroupLayout.SequentialGroup pinVertical = mainPanelLayout.createSequentialGroup(); + +                if (pinLabelPos == PinLabelPosition.ABOVE) { +                  if (changePin) { +                    pinHorizontal +                            .addComponent(oldPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) +                            .addComponent(oldPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE); +                    pinVertical +                            .addComponent(oldPinLabel) +                            .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +                            .addComponent(oldPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) +                            .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED); +                  } +                  pinHorizontal  +                          .addComponent(pinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) +                          .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) +                          .addComponent(repeatPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) +                          .addComponent(repeatPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) +                          .addGroup(mainPanelLayout.createSequentialGroup() +                            .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) +                            .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)); +                  pinVertical +                          .addComponent(pinLabel) +                          .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +                          .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) +                          .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +                          .addComponent(repeatPinLabel) +                          .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +                          .addComponent(repeatPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) +                          .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +                          .addComponent(pinsizeLabel); +                } else { +                  if (changePin) { +                    pinHorizontal +                          .addGroup(mainPanelLayout.createSequentialGroup() +                            .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) +                              .addComponent(oldPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) +                              .addComponent(pinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) +                              .addComponent(repeatPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) +                            .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +                            .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) +                              .addComponent(oldPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) +                              .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) +                              .addComponent(repeatPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))); + +                    pinVertical +                          .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) +                            .addComponent(oldPinLabel) +                            .addComponent(oldPinField)) +                          .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED); +                  } else { +                    pinHorizontal +                          .addGroup(mainPanelLayout.createSequentialGroup() +                            .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) +                              .addComponent(pinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) +                              .addComponent(repeatPinLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)) +                            .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +                            .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) +                              .addComponent(pinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) +                              .addComponent(repeatPinField, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))); + +                  } +                  pinHorizontal +                          .addGroup(mainPanelLayout.createSequentialGroup() +                            .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) +                            .addComponent(pinsizeLabel, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)); +                  pinVertical +                          .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) +                            .addComponent(pinLabel) +                            .addComponent(pinField)) +                          .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +                          .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) +                            .addComponent(repeatPinLabel) +                            .addComponent(repeatPinField)) +                          .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +                          .addComponent(pinsizeLabel); +                } + +                mainPanelLayout.setHorizontalGroup( +                  mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) +                    .addGroup(infoHorizontal) +                    .addGroup(pinHorizontal)); + +                mainPanelLayout.setVerticalGroup( +                  mainPanelLayout.createSequentialGroup() +                    .addGroup(infoVertical) +                    .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +                    .addGroup(pinVertical)); + +                GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); +                buttonPanel.setLayout(buttonPanelLayout); + +                GroupLayout.SequentialGroup buttonHorizontal = buttonPanelLayout.createSequentialGroup() +                        .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) +                        .addComponent(okButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); +                GroupLayout.Group buttonVertical; + +                JButton cancelButton = new JButton(); +                cancelButton.setFont(cancelButton.getFont().deriveFont(cancelButton.getFont().getStyle() & ~java.awt.Font.BOLD)); +                cancelButton.setText(messages.getString(BUTTON_CANCEL)); +                cancelButton.setActionCommand(cancelCommand); +                cancelButton.addActionListener(cancelListener); + +                buttonHorizontal +                        .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED) +                        .addComponent(cancelButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE); +                buttonVertical = buttonPanelLayout.createParallelGroup(GroupLayout.Alignment.BASELINE) +                        .addComponent(okButton) +                        .addComponent(cancelButton); + +                buttonPanelLayout.setHorizontalGroup(buttonHorizontal); +                buttonPanelLayout.setVerticalGroup(buttonVertical); + +                if (oldPinField != null) { +                  oldPinField.requestFocusInWindow(); +                } else { +                  pinField.requestFocusInWindow(); +                } +                contentPanel.validate(); + +            } +        }); +  } + +  @Override +  public void showChangePINDialog(final PINSpec pin, +          final ActionListener okListener, final String okCommand, +          final ActionListener cancelListener, final String cancelCommand) { +     +      log.debug("scheduling change pin dialog"); +      showPINDialog(true, pin, okListener, okCommand, cancelListener, cancelCommand); +  } + +  @Override +  public void showUnblockPINDialog(final PINSpec pin, +          final ActionListener okListener, final String okCommand, +          final ActionListener cancelListener, final String cancelCommand) { + +      log.debug("scheduling unblock PIN dialog"); + +      SwingUtilities.invokeLater(new Runnable() { + +          @Override +            public void run() { + +                log.debug("show unblock PIN dialog"); + +                log.error("unblock pin not supported"); + +                mainPanel.removeAll(); +                buttonPanel.removeAll(); + +                if (renderHeaderPanel) { +                  titleLabel.setText(messages.getString(TITLE_ERROR)); +                } + +                helpListener.setHelpTopic(HELP_PINMGMT); + +                String errorMsgPattern = cardmgmtMessages.getString(ERR_UNBLOCK); +                String errorMsg = MessageFormat.format(errorMsgPattern, pin.getLocalizedName()); + +                JLabel errorMsgLabel = new JLabel(); +                errorMsgLabel.setFont(errorMsgLabel.getFont().deriveFont(errorMsgLabel.getFont().getStyle() & ~java.awt.Font.BOLD)); +                errorMsgLabel.setText(errorMsg); + +                GroupLayout mainPanelLayout = new GroupLayout(mainPanel); +                mainPanel.setLayout(mainPanelLayout); + +                GroupLayout.ParallelGroup mainHorizontal = mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING); +                GroupLayout.SequentialGroup mainVertical = mainPanelLayout.createSequentialGroup(); + +                if (!renderHeaderPanel) { +                  JLabel errorTitleLabel = new JLabel(); +                  errorTitleLabel.setFont(errorTitleLabel.getFont().deriveFont(errorTitleLabel.getFont().getStyle() | java.awt.Font.BOLD)); +                  errorTitleLabel.setText(messages.getString(TITLE_ERROR)); +                  errorTitleLabel.setForeground(ERROR_COLOR); + +                  mainHorizontal +                          .addGroup(mainPanelLayout.createSequentialGroup() +                            .addComponent(errorTitleLabel) +                            .addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED, 0, Short.MAX_VALUE) +                            .addComponent(helpLabel)); +                  mainVertical +                          .addGroup(mainPanelLayout.createParallelGroup(GroupLayout.Alignment.LEADING) +                            .addComponent(errorTitleLabel) +                            .addComponent(helpLabel)); +                } + +                mainPanelLayout.setHorizontalGroup(mainHorizontal +                        .addComponent(errorMsgLabel)); +                mainPanelLayout.setVerticalGroup(mainVertical +                        .addComponent(errorMsgLabel)); + +                JButton okButton = new JButton(); +                okButton.setFont(okButton.getFont().deriveFont(okButton.getFont().getStyle() & ~java.awt.Font.BOLD)); +                okButton.setText(messages.getString(BUTTON_OK)); +                okButton.setActionCommand(cancelCommand); +                okButton.addActionListener(cancelListener); + +                GroupLayout buttonPanelLayout = new GroupLayout(buttonPanel); +                buttonPanel.setLayout(buttonPanelLayout); + +                buttonPanelLayout.setHorizontalGroup( +                  buttonPanelLayout.createSequentialGroup() +                        .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) +                        .addComponent(okButton, GroupLayout.PREFERRED_SIZE, buttonSize, GroupLayout.PREFERRED_SIZE)); +                buttonPanelLayout.setVerticalGroup( +                  buttonPanelLayout.createSequentialGroup() +                    .addComponent(okButton)); + +                contentPanel.validate(); +            } +        });    } diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java index 3d653fab..2a8f28d2 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINManagementGUIFacade.java @@ -17,7 +17,9 @@  package at.gv.egiz.bku.gui; +import at.gv.egiz.smcc.PINSpec;  import java.awt.event.ActionListener; +import java.util.Map;  /**   * @@ -27,8 +29,49 @@ public interface PINManagementGUIFacade extends BKUGUIFacade {    public static final String HELP_PINMGMT = "help.pin.mgmt";    public static final String TITLE_PINMGMT = "title.pin.mgmt"; +  public static final String TITLE_ACTIVATE_PIN = "title.activate.pin"; +  public static final String TITLE_CHANGE_PIN = "title.change.pin"; +  public static final String TITLE_UNBLOCK_PIN = "title.unblock.pin";    public static final String MESSAGE_PINMGMT = "message.pin.mgmt"; -   -  public void showPINManagementDialog(PINStatusProvider pinStatusProvider, ActionListener activateListener, String activateCmd, ActionListener changeListener, String changeCmd, ActionListener unblockListener, String unblockCmd, ActionListener cancelListener, String cancelCmd); +  public static final String MESSAGE_ACTIVATE_PIN = "message.activate.pin"; +  public static final String MESSAGE_CHANGE_PIN = "message.change.pin"; +  public static final String MESSAGE_UNBLOCK_PIN = "message.unblock.pin"; +  public static final String LABEL_OLD_PIN = "label.old.pin"; +  public static final String LABEL_NEW_PIN = "label.new.pin"; +  public static final String LABEL_REPEAT_PIN = "label.repeat.pin"; +  public static final String ERR_ACTIVATE = "err.activate"; +  public static final String ERR_CHANGE = "err.change"; +  public static final String ERR_UNBLOCK = "err.unblock"; + +  public static final String BUTTON_ACTIVATE = "button.activate"; +  public static final String BUTTON_UNBLOCK = "button.unblock"; +  public static final String BUTTON_CHANGE = "button.change"; + +  public static final String STATUS_ACTIVE = "status.active"; +  public static final String STATUS_BLOCKED = "status.blocked"; +  public static final String STATUS_NOT_ACTIVE = "status.not.active"; +  public static final String STATUS_UNKNOWN = "status.unknown"; + +  public enum STATUS { ACTIV, NOT_ACTIV, BLOCKED, UNKNOWN }; + +  public void showPINManagementDialog(Map<PINSpec, STATUS> pins, +          ActionListener activateListener, String activateCmd, String changeCmd, String unblockCmd, +          ActionListener cancelListener, String cancelCmd); + +  public void showActivatePINDialog(PINSpec pin, +          ActionListener okListener, String okCmd, +          ActionListener cancelListener, String cancelCmd); + +  public void showChangePINDialog(PINSpec pin, +          ActionListener okListener, String okCmd, +          ActionListener cancelListener, String cancelCmd); + +  public void showUnblockPINDialog(PINSpec pin, +          ActionListener okListener, String okCmd, +          ActionListener cancelListener, String cancelCmd); + +  public char[] getOldPin(); + +  public PINSpec getSelectedPIN();  } diff --git a/STALExt/src/main/java/at/gv/egiz/stal/ext/ChangePINRequest.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINSpecRenderer.java index ea508146..e3d73e1f 100644 --- a/STALExt/src/main/java/at/gv/egiz/stal/ext/ChangePINRequest.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINSpecRenderer.java @@ -15,14 +15,25 @@   * limitations under the License.   */ -package at.gv.egiz.stal.ext; +package at.gv.egiz.bku.gui; -import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.smcc.PINSpec; +import javax.swing.table.DefaultTableCellRenderer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory;  /**   *   * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>   */ -public class ChangePINRequest extends STALRequest { +public class PINSpecRenderer extends DefaultTableCellRenderer { + +  private static final Log log = LogFactory.getLog(PINSpecRenderer.class); + +  @Override +  protected void setValue(Object value) { +    PINSpec pinSpec = (PINSpec) value; +    super.setText(pinSpec.getLocalizedName()); +  }  } diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusRenderer.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusRenderer.java new file mode 100644 index 00000000..2f8852ff --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusRenderer.java @@ -0,0 +1,63 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + *  + * Licensed 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 at.gv.egiz.bku.gui; + +import at.gv.egiz.bku.gui.PINManagementGUIFacade.STATUS; +import java.awt.Color; +import java.awt.Font; +import java.util.ResourceBundle; +import javax.swing.table.DefaultTableCellRenderer; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> + */ +public class PINStatusRenderer extends DefaultTableCellRenderer { +   +  private static final Log log = LogFactory.getLog(PINStatusRenderer.class); + +  public static final Color RED = new Color(0.9f, 0.0f, 0.0f); +  public static final Color GREEN = new Color(0.0f, 0.8f, 0.0f); +  protected ResourceBundle messages; + +  public PINStatusRenderer(ResourceBundle messages) { +    this.messages = messages; +  } + +  @Override +  protected void setValue(Object value) { +    STATUS pinStatus = (STATUS) value; +    super.setFont(super.getFont().deriveFont(super.getFont().getStyle() | Font.BOLD)); +       +    if (pinStatus == STATUS.NOT_ACTIV) { +      super.setForeground(RED); +      super.setText("<html>" + messages.getString(PINManagementGUIFacade.STATUS_NOT_ACTIVE) + "</html>"); +    } else if (pinStatus == STATUS.ACTIV) { +      super.setForeground(GREEN); +      super.setText("<html>" + messages.getString(PINManagementGUIFacade.STATUS_ACTIVE) + "</html>"); +    } else if (pinStatus == STATUS.BLOCKED) { +      super.setForeground(RED); +      super.setText("<html>" + messages.getString(PINManagementGUIFacade.STATUS_BLOCKED) + "</html>"); +    } else { +      super.setForeground(Color.BLACK); +      super.setText("<html>" + messages.getString(PINManagementGUIFacade.STATUS_UNKNOWN) + "</html>"); +    } +  } +} diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusTableModel.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusTableModel.java new file mode 100644 index 00000000..feaa5072 --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusTableModel.java @@ -0,0 +1,60 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + *  + * Licensed 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 at.gv.egiz.bku.gui; + +import at.gv.egiz.bku.gui.PINManagementGUIFacade.STATUS; +import at.gv.egiz.smcc.PINSpec; +import java.util.Map; +import javax.swing.table.DefaultTableModel; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> + */ +public class PINStatusTableModel extends DefaultTableModel { + +  protected static final Log log = LogFactory.getLog(PINStatusTableModel.class); +  protected Class[] types; + +  public PINStatusTableModel(Map<PINSpec, STATUS> pinStatuses) { +    super(0, 2); +    if (pinStatuses == null) { +      throw new RuntimeException("pinStatuses must not be null"); +    } +    log.trace(pinStatuses.size() + " PINs"); +    types = new Class[] { PINSpec.class, STATUS.class }; +    for (PINSpec pinSpec : pinStatuses.keySet()) { +      addRow(new Object[] { pinSpec, pinStatuses.get(pinSpec) }); +    } +//    PINSpec activePIN = new PINSpec(0, 1, null, "active-PIN", (byte) 0x01); +//    PINSpec blockedPIN = new PINSpec(0, 1, null, "blocked-PIN", (byte) 0x01); +//    addRow(new Object[] { activePIN, PINStatusProvider.STATUS.ACTIV }); +//    addRow(new Object[] { blockedPIN, PINStatusProvider.STATUS.BLOCKED }); +  } + +  @Override +  public Class getColumnClass(int columnIndex) { +    return types[columnIndex]; +  } + +  @Override +  public boolean isCellEditable(int rowIndex, int columnIndex) { +    return false; +  } +} diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementApplet.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementApplet.java index 72d06618..d948ac03 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementApplet.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementApplet.java @@ -19,6 +19,7 @@ package at.gv.egiz.bku.online.applet;  import at.gv.egiz.bku.gui.AbstractHelpListener;  import at.gv.egiz.bku.gui.BKUGUIFacade;  import at.gv.egiz.bku.gui.PINManagementGUI; +import at.gv.egiz.bku.gui.PINManagementGUIFacade;  import java.awt.Container;  import java.net.URL;  import java.util.Locale; @@ -45,6 +46,6 @@ public class PINManagementApplet extends BKUApplet {    @Override    protected AppletBKUWorker createBKUWorker(BKUApplet applet, BKUGUIFacade gui) { -    return new PINManagementBKUWorker(applet, gui); +    return new PINManagementBKUWorker(applet, (PINManagementGUIFacade) gui);    }  } diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementBKUWorker.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementBKUWorker.java index e65d98ca..ffd83e42 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementBKUWorker.java +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/online/applet/PINManagementBKUWorker.java @@ -18,35 +18,28 @@ package at.gv.egiz.bku.online.applet;  import at.gv.egiz.bku.gui.BKUGUIFacade;  import at.gv.egiz.bku.gui.PINManagementGUIFacade; -import at.gv.egiz.bku.smccstal.ext.PINMgmtRequestHandler; +import at.gv.egiz.bku.smccstal.ext.PINManagementRequestHandler; +import at.gv.egiz.stal.ErrorResponse;  import at.gv.egiz.stal.STALResponse; -import at.gv.egiz.stal.ext.ActivatePINRequest; -import at.gv.egiz.stal.ext.ChangePINRequest; -import at.gv.egiz.stal.ext.UnblockPINRequest; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.util.Collection; +import at.gv.egiz.stal.ext.PINManagementRequest; +import at.gv.egiz.stal.ext.PINManagementResponse;  import java.util.Collections;  import java.util.List;  import java.util.logging.Level;  import java.util.logging.Logger;  /** - * + * This BKU Worker does not connect to STAL webservice + * (no Internet connection permitted while activating PINs). + *    * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>   */  public class PINManagementBKUWorker extends AppletBKUWorker { -  protected PINMgmtRequestHandler handler = new PINMgmtRequestHandler(); -  protected PINManagementActionListener listener = new PINManagementActionListener(); - -  public PINManagementBKUWorker(BKUApplet applet, BKUGUIFacade gui) { +  public PINManagementBKUWorker(BKUApplet applet, PINManagementGUIFacade gui) {      super(applet, gui);      handlerMap.clear(); -//    PINMgmtRequestHandler handler = new PINMgmtRequestHandler(); -//    addRequestHandler(ActivatePINRequest.class, handler); -//    addRequestHandler(ChangePINRequest.class, handler); -//    addRequestHandler(UnblockPINRequest.class, handler); +    addRequestHandler(PINManagementRequest.class, new PINManagementRequestHandler());    }    @Override @@ -54,22 +47,24 @@ public class PINManagementBKUWorker extends AppletBKUWorker {      gui.showWelcomeDialog();      try { - -      if (waitForCard()) { -        gui.showErrorDialog("no card, canceled PIN mgmt dialog", null); +      List<STALResponse> responses = handleRequest(Collections.singletonList(new PINManagementRequest())); + +      if (responses.size() == 1) { +        STALResponse response = responses.get(0); +        if (response instanceof PINManagementResponse) { +          log.debug("PIN management dialog finished"); +        } else if (response instanceof ErrorResponse) { +          showErrorDialog(BKUGUIFacade.ERR_UNKNOWN, null); +        } else { +          throw new RuntimeException("Invalid STAL response: " + response.getClass().getName()); +        } +      } else { +        throw new RuntimeException("invalid number of STAL responses: " + responses.size());        } -      actionCommandList.clear(); -      actionCommandList.add("cancel"); - -      ((PINManagementGUIFacade) gui).showPINManagementDialog(handler, -              listener, "activate", -              listener, "change", -              listener, "unblock", -              this, "cancel"); - -      waitForAction(); - +    } catch (RuntimeException ex) { +      log.error("unexpected error: " + ex.getMessage(), ex); +      showErrorDialog(BKUGUIFacade.ERR_UNKNOWN, null);      } catch (Exception ex) {        log.error(ex.getMessage(), ex);        showErrorDialog(BKUGUIFacade.ERR_UNKNOWN_WITH_PARAM, ex); @@ -82,31 +77,4 @@ public class PINManagementBKUWorker extends AppletBKUWorker {      applet.sendRedirect(sessionId);    } -  protected class PINManagementActionListener implements ActionListener { - -    @Override -    public void actionPerformed(ActionEvent e) { -      try { -        String cmd = e.getActionCommand(); -        if ("activate".equals(cmd)) { -          //create STAL request, call handle(req) -          ActivatePINRequest stalReq = new ActivatePINRequest(); -          STALResponse stalResp = handler.handleRequest(stalReq); -          gui.showErrorDialog(BKUGUIFacade.ERR_UNKNOWN_WITH_PARAM, new Object[]{"debug"}, this, "back"); -        } else if ("change".equals(cmd)) { -        } else if ("unblock".equals(cmd)) { -        } else if ("back".equals(cmd)) { - -          ((PINManagementGUIFacade) gui).showPINManagementDialog(handler, -                  this, "activate", -                  this, "change", -                  this, "unblock", -                  PINManagementBKUWorker.this, "cancel"); - -        } -      } catch (InterruptedException ex) { -        log.fatal(ex); -      } -    }    } -} diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINManagementRequestHandler.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINManagementRequestHandler.java new file mode 100644 index 00000000..fcef3191 --- /dev/null +++ b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINManagementRequestHandler.java @@ -0,0 +1,331 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + *  + * Licensed 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 at.gv.egiz.bku.smccstal.ext; + +import at.gv.egiz.bku.gui.BKUGUIFacade; +import at.gv.egiz.bku.gui.PINManagementGUIFacade; +import at.gv.egiz.bku.gui.PINManagementGUIFacade.STATUS; +import at.gv.egiz.bku.smccstal.AbstractRequestHandler; +import at.gv.egiz.smcc.PINSpec; +import at.gv.egiz.smcc.SignatureCardException; +import at.gv.egiz.smcc.util.SMCCHelper; +import at.gv.egiz.stal.ErrorResponse; +import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.stal.STALResponse; +import at.gv.egiz.stal.ext.PINManagementRequest; +import at.gv.egiz.stal.ext.PINManagementResponse; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import javax.smartcardio.Card; +import javax.smartcardio.CardChannel; +import javax.smartcardio.CardException; +import javax.smartcardio.CommandAPDU; +import javax.smartcardio.ResponseAPDU; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> + */ +public class PINManagementRequestHandler extends AbstractRequestHandler { + +  public static final String ERR_NOPIN_SELECTED = "err.no.pin.selected"; +  protected static final Log log = LogFactory.getLog(PINManagementRequestHandler.class); + +//  protected ResourceBundle messages; + +//  public PINManagementRequestHandler(ResourceBundle messages) { +//    this.messages = messages; +//  } +  @Override +  public STALResponse handleRequest(STALRequest request) throws InterruptedException { +    if (request instanceof PINManagementRequest) { + +      PINManagementGUIFacade gui = (PINManagementGUIFacade) this.gui; + +      showPINManagementDialog(gui); + +      while (true) { + +        waitForAction(); + +        if ("cancel".equals(actionCommand)) { +          return new PINManagementResponse(); +        } else if ("back".equals(actionCommand)) { +          showPINManagementDialog(gui); +        } else { +          PINSpec selectedPIN = gui.getSelectedPIN(); + +          if (selectedPIN == null) { +            throw new RuntimeException("no PIN selected for activation/change"); +          } + +          if ("activate_enterpin".equals(actionCommand)) { +            gui.showActivatePINDialog(selectedPIN, this, "activate", this, "back"); +          } else if ("change_enterpin".equals(actionCommand)) { +            gui.showChangePINDialog(selectedPIN, this, "change", this, "back"); +          } else if ("unblock_enterpuk".equals(actionCommand)) { +            gui.showUnblockPINDialog(selectedPIN, this, "unblock", this, "back"); +          } else if ("activate".equals(actionCommand)) { +            try { +              byte[] pin = encodePIN(gui.getPin()); +              activatePIN(selectedPIN.getKID(), selectedPIN.getContextAID(), pin); +              showPINManagementDialog(gui); +            } catch (SignatureCardException ex) { +              log.error("failed to activate " + selectedPIN.getLocalizedName() + ": " + ex.getMessage()); +              gui.showErrorDialog(PINManagementGUIFacade.ERR_ACTIVATE,  +                      new Object[] {selectedPIN.getLocalizedName()}, +                      this, "cancel"); +            } +          } else if ("change".equals(actionCommand)) { +            try { +              byte[] oldPin = encodePIN(gui.getOldPin()); //new byte[]{(byte) 0x25, (byte) 0x40, (byte) 0x01}; +              byte[] pin = encodePIN(gui.getPin()); //new byte[]{(byte) 0x25, (byte) 0x40}; +              changePIN(selectedPIN.getKID(), selectedPIN.getContextAID(), oldPin, pin); +              showPINManagementDialog(gui); +            } catch (SignatureCardException ex) { +              log.error("failed to change " + selectedPIN.getLocalizedName() + ": " + ex.getMessage()); +              gui.showErrorDialog(PINManagementGUIFacade.ERR_CHANGE,  +                      new Object[] {selectedPIN.getLocalizedName()}, +                      this, "cancel"); +            } +          } else if ("unblock".equals(actionCommand)) { +            log.error("unblock PIN not implemented"); +            gui.showErrorDialog(PINManagementGUIFacade.ERR_UNBLOCK, null, this, "cancel"); +          } else { +            throw new RuntimeException("unsupported action " + actionCommand); +          } +        } +      } +    } else { +      log.error("Got unexpected STAL request: " + request); +      return new ErrorResponse(1000); +    } +  } + +  @Override +  public boolean requireCard() { +    return true; +  } + +  /** +   * pin.length < 4bit +   * @param kid +   * @param contextAID +   * @param pin +   * @throws at.gv.egiz.smcc.SignatureCardException +   */ +  private void activatePIN(byte kid, byte[] contextAID, byte[] pin) throws SignatureCardException { +    try { +      Card icc = card.getCard(); +      icc.beginExclusive(); +      CardChannel channel = icc.getBasicChannel(); + +      if (contextAID != null) { +        CommandAPDU selectAPDU = new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, contextAID); +        ResponseAPDU responseAPDU = channel.transmit(selectAPDU); +        if (responseAPDU.getSW() != 0x9000) { +          String msg = "Failed to activate PIN " + SMCCHelper.toString(new byte[]{kid}) + +                  ": Failed to select AID " + SMCCHelper.toString(contextAID) + +                  ": " + SMCCHelper.toString(responseAPDU.getBytes()); +          log.error(msg); +          throw new SignatureCardException(msg); +        } +      } + +      if (pin.length > 7) { +        log.error("Invalid PIN"); +        throw new SignatureCardException("Invalid PIN"); +      } +      byte length = (byte) (0x20 | pin.length * 2); + +      byte[] apdu = new byte[]{ +        (byte) 0x00, (byte) 0x24, (byte) 0x01, kid, (byte) 0x08, +        (byte) length, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF}; +      for (int i = 0; i < pin.length; i++) { +        apdu[i + 6] = pin[i]; +      } + +      CommandAPDU verifyAPDU = new CommandAPDU(apdu); +      ResponseAPDU responseAPDU = channel.transmit(verifyAPDU); + +      if (responseAPDU.getSW() != 0x9000) { +        String msg = "Failed to activate PIN " + SMCCHelper.toString(new byte[]{kid}) + ": " + SMCCHelper.toString(responseAPDU.getBytes()); +        log.error(msg); +        throw new SignatureCardException(msg); +      } + + +      icc.endExclusive(); + + +    } catch (CardException ex) { +      log.error("Failed to get PIN status: " + ex.getMessage()); +      throw new SignatureCardException("Failed to get PIN status", ex); +    } +  } + +  private void changePIN(byte kid, byte[] contextAID, byte[] oldPIN, byte[] newPIN) throws SignatureCardException { +    try { +      Card icc = card.getCard(); +      icc.beginExclusive(); +      CardChannel channel = icc.getBasicChannel(); + +      if (contextAID != null) { +        CommandAPDU selectAPDU = new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, contextAID); +        ResponseAPDU responseAPDU = channel.transmit(selectAPDU); +        if (responseAPDU.getSW() != 0x9000) { +          String msg = "Failed to change PIN " + SMCCHelper.toString(new byte[]{kid}) + +                  ": Failed to select AID " + SMCCHelper.toString(contextAID) + +                  ": " + SMCCHelper.toString(responseAPDU.getBytes()); +          log.error(msg); +          throw new SignatureCardException(msg); +        } +      } + +      if (oldPIN.length > 7 || newPIN.length > 7) { +        log.error("Invalid PIN"); +        throw new SignatureCardException("Invalid PIN"); +      } +      byte oldLength = (byte) (0x20 | oldPIN.length * 2); +      byte newLength = (byte) (0x20 | newPIN.length * 2); + +      byte[] apdu = new byte[]{ +        (byte) 0x00, (byte) 0x24, (byte) 0x00, kid, (byte) 0x10, +        oldLength, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, +        newLength, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF, (byte) 0xFF}; +      for (int i = 0; i < oldPIN.length; i++) { +        apdu[i + 6] = oldPIN[i]; +      } +      for (int i = 0; i < newPIN.length; i++) { +        apdu[i + 14] = newPIN[i]; +      } + +      CommandAPDU verifyAPDU = new CommandAPDU(apdu); +      ResponseAPDU responseAPDU = channel.transmit(verifyAPDU); + +      if (responseAPDU.getSW() != 0x9000) { +        String msg = "Failed to change PIN " + SMCCHelper.toString(new byte[]{kid}) + ": " + SMCCHelper.toString(responseAPDU.getBytes()); +        log.error(msg); +        throw new SignatureCardException(msg); +      } + + +      icc.endExclusive(); + + +    } catch (CardException ex) { +      log.error("Failed to get PIN status: " + ex.getMessage()); +      throw new SignatureCardException("Failed to get PIN status", ex); +    } +  } + +  public Map<PINSpec, STATUS> getPINStatuses() throws SignatureCardException { +    try { +      Card icc = card.getCard(); +      icc.beginExclusive(); +      CardChannel channel = icc.getBasicChannel(); + +      HashMap<PINSpec, STATUS> pinStatuses = new HashMap<PINSpec, STATUS>(); +      List<PINSpec> pins = card.getPINSpecs(); + +      //select DF_SichereSignatur 00 A4 04 0C 08 D0 40 00 00 17 00 12 01 +//      CommandAPDU selectAPDU = new CommandAPDU(new byte[]{(byte) 0x00, (byte) 0xa4, (byte) 0x04, (byte) 0x0c, (byte) 0x08, +//                (byte) 0xd0, (byte) 0x40, (byte) 0x00, (byte) 0x00, (byte) 0x17, (byte) 0x00, (byte) 0x12, (byte) 0x01}); +//      ResponseAPDU rAPDU = channel.transmit(selectAPDU); +//      log.debug("SELECT FILE DF_SichereSignatur: " + SMCCHelper.toString(rAPDU.getBytes())); + +      //select DF_SIG DF 70 +//      CommandAPDU selectAPDU = new CommandAPDU(new byte[]{(byte) 0x00, (byte) 0xa4, (byte) 0x00, (byte) 0x0c, (byte) 0x02, +//                (byte) 0xdf, (byte) 0x70 }); +//      ResponseAPDU rAPDU = channel.transmit(selectAPDU); +//      log.debug("SELECT FILE DF_SIG: " + SMCCHelper.toString(rAPDU.getBytes())); + +      //select DF_DEC DF 71 +//      CommandAPDU selectAPDU = new CommandAPDU(new byte[]{(byte) 0x00, (byte) 0xa4, (byte) 0x04, (byte) 0x0c, (byte) 0x08, +//                (byte) 0xd0, (byte) 0x40, (byte) 0x00, (byte) 0x00, (byte) 0x17, (byte) 0x00, (byte) 0x12, (byte) 0x01}); +//      ResponseAPDU rAPDU = channel.transmit(selectAPDU); +//      log.debug("SELECT FILE DF_SichereSignatur: " + SMCCHelper.toString(rAPDU.getBytes())); + +      for (PINSpec pinSpec : pins) { +        byte kid = pinSpec.getKID(); +        byte[] contextAID = pinSpec.getContextAID(); + +        if (contextAID != null) { +          CommandAPDU selectAPDU = new CommandAPDU(0x00, 0xa4, 0x04, 0x0c, contextAID); +          ResponseAPDU responseAPDU = channel.transmit(selectAPDU); +          if (responseAPDU.getSW() != 0x9000) { +            String msg = "Failed to activate PIN " + SMCCHelper.toString(new byte[]{kid}) + +                    ": Failed to select AID " + SMCCHelper.toString(contextAID) + +                    ": " + SMCCHelper.toString(responseAPDU.getBytes()); +            log.error(msg); +            throw new SignatureCardException(msg); +          } +        } + +        CommandAPDU verifyAPDU = new CommandAPDU(new byte[]{(byte) 0x00, (byte) 0x20, (byte) 00, kid}); +        ResponseAPDU responseAPDU = channel.transmit(verifyAPDU); + +        STATUS status = STATUS.UNKNOWN; +        if (responseAPDU.getSW() == 0x6984) { +          status = STATUS.NOT_ACTIV; +        } else if (responseAPDU.getSW() == 0x63c0) { +          status = STATUS.BLOCKED; +        } else if (responseAPDU.getSW1() == 0x63) { +          status = STATUS.ACTIV; +        } +        if (log.isDebugEnabled()) { +          log.debug("PIN " + pinSpec.getLocalizedName() + " status: " + SMCCHelper.toString(responseAPDU.getBytes())); +        } + +        pinStatuses.put(pinSpec, status); +      } +      icc.endExclusive(); + +      return pinStatuses; + +    } catch (CardException ex) { +      log.error("Failed to get PIN status: " + ex.getMessage()); +      throw new SignatureCardException("Failed to get PIN status", ex); +    } +  } + +  private byte[] encodePIN(char[] pinChars) { +    int length = (int) Math.ceil(pinChars.length/2); +    byte[] pin = new byte[length]; +    for (int i = 0; i < length; i++) { +      pin[i] = (byte) (16*Character.digit(pinChars[i*2], 16) + Character.digit(pinChars[i*2+1], 16)); +    } +    log.trace("***** "  + SMCCHelper.toString(pin) + " ******"); +    return pin; +  } + +  private void showPINManagementDialog(PINManagementGUIFacade gui) { +    try { +      Map<PINSpec, STATUS> pins = getPINStatuses(); +      gui.showPINManagementDialog(pins,  +              this, "activate_enterpin", "change_enterpin", "unblock_enterpuk", +              this, "cancel"); +    } catch (SignatureCardException ex) { +      gui.showErrorDialog(BKUGUIFacade.ERR_UNKNOWN_WITH_PARAM,  +              new Object[]{"FAILED TO GET PIN STATUSES: " + ex.getMessage()}, +              this, "cancel"); +    } +  } +} diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINMgmtRequestHandler.java b/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINMgmtRequestHandler.java deleted file mode 100644 index b2d34ff2..00000000 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/smccstal/ext/PINMgmtRequestHandler.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2008 Federal Chancellery Austria and - * Graz University of Technology - *  - * Licensed 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 at.gv.egiz.bku.smccstal.ext; - -import at.gv.egiz.bku.gui.PINStatusProvider; -import at.gv.egiz.bku.smccstal.AbstractRequestHandler; -import at.gv.egiz.smcc.SignatureCardException; -import at.gv.egiz.stal.ErrorResponse; -import at.gv.egiz.stal.STALRequest; -import at.gv.egiz.stal.STALResponse; -import at.gv.egiz.stal.ext.ActivatePINRequest; -import at.gv.egiz.stal.ext.ChangePINRequest; -import at.gv.egiz.stal.ext.UnblockPINRequest; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.smartcardio.Card; -import javax.smartcardio.CardChannel; -import javax.smartcardio.CardException; -import javax.smartcardio.CommandAPDU; -import javax.smartcardio.ResponseAPDU; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * - * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> - */ -public class PINMgmtRequestHandler extends AbstractRequestHandler implements PINStatusProvider { - -  protected static final Log log = LogFactory.getLog(PINMgmtRequestHandler.class); - -  @Override -  public STALResponse handleRequest(STALRequest request) throws InterruptedException { -    if (request instanceof ActivatePINRequest) { -      log.error("not implemented yet"); -      return new ErrorResponse(1000); - -    } else if (request instanceof ChangePINRequest) { -      log.error("not implemented yet"); -      return new ErrorResponse(1000); - -    } else if (request instanceof UnblockPINRequest) { -      log.error("not implemented yet"); -      return new ErrorResponse(1000); - -    } else { -      log.error("Got unexpected STAL request: " + request); -      return new ErrorResponse(1000); -    } -  } - -  @Override -  public boolean requireCard() { -    return true; -  } - -  @Override -  public STATUS getPINStatus(int pin) throws SignatureCardException { -    try { -      Card icc = card.getCard(); -      icc.beginExclusive(); -      CardChannel channel = icc.getBasicChannel(); -      CommandAPDU verifyAPDU = new CommandAPDU(new byte[] {(byte) 0x00} ); -      ResponseAPDU responseAPDU = channel.transmit(verifyAPDU); -      byte sw1 = (byte) responseAPDU.getSW1(); -      byte[] sw = new byte[] { -                (byte) (0xFF & responseAPDU.getSW1()), -                (byte) (0xFF & responseAPDU.getSW2()) }; - -      icc.endExclusive(); -      return STATUS.ACTIV; -    } catch (CardException ex) { -      log.error("Failed to get PIN status: " + ex.getMessage()); -      throw new SignatureCardException("Failed to get PIN status", ex); -    } -  } - -} diff --git a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties index 469af15f..e51044af 100644 --- a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties +++ b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages.properties @@ -15,10 +15,34 @@  title.activation=<html>Aktivierung</html>  title.pin.mgmt=<html>PIN Verwaltung</html> -message.pin.mgmt=<html>under construction</html> +title.activate.pin=<html>PIN Aktivieren</html> +title.change.pin=<html>PIN \u00C4ndern</html> +title.unblock.pin=<html>PIN Entsperren</html> + +message.pin.mgmt=<html>Die Karte verf\u00FCgt \u00FCber {0} PINs</html> +message.activate.pin=<html>{0} eingeben und best\u00E4tigen</html> +message.change.pin=<html>{0} eingeben und best\u00E4tigen</html> +message.unblock.pin=<html>PUK zu {0} eingeben</html> +  label.activation=<html>e-card Aktivierungsprozess</html>  label.activation.step=<html>Schritt {0}</html>  label.activation.idle=<html>Warte auf Server...</html> +label.old.pin=<html>Alte {0}:</html> +label.new.pin=<html>Neue {0}:</html> +label.repeat.pin=<html>Best\u00E4tigung:</html> +  button.activate=Aktivieren  button.change=\u00C4ndern -button.unblock=Entsperren
\ No newline at end of file +button.unblock=Entsperren + +help.activation=help.activation +help.pin.mgmt=help.pin.mgmt + +err.activate=<html>Beim Aktivieren der {0} trat ein Fehler auf.</html> +err.change=<html>Beim \u00C4ndern der {0} trat ein Fehler auf.</html> +err.unblock=<html>Das Entsperren der {0} wird nicht unterst\u00FCtzt.</html> + +status.not.active=NICHT AKTIV +status.active=AKTIV +status.blocked=GESPERRT +status.unknown=UNBEKANNT diff --git a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties index 16ac7d0b..1cf4a102 100644 --- a/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties +++ b/BKUAppletExt/src/main/resources/at/gv/egiz/bku/gui/ActivationMessages_en.properties @@ -13,12 +13,36 @@  # See the License for the specific language governing permissions and  # limitations under the License. -title.activation=<html>Aktivation</html> +title.activation=<html>Activation</html>  title.pin.mgmt=<html>PIN Management</html> -message.pin.mgmt=<html>under construction</html> +title.activate.pin=<html>Activate PIN</html> +title.change.pin=<html>Change PIN</html> +title.unblock.pin=<html>Unblock PIN</html> + +message.pin.mgmt=<html>The smartcard has {0} PINs</html> +message.activate.pin=<html>Enter and confirm {0}</html> +message.change.pin=<html>Enter and confirm {0}</html> +message.unblock.pin=<html>Enter PUK for {0}</html> +  label.activation=<html>e-card activation process</html>  label.activation.step=<html>Step {0}</html>  label.activation.idle=<html>Wait for server...</html> +label.old.pin=<html>Old {0}:</html> +label.new.pin=<html>New {0}:</html> +label.repeat.pin=<html>Confirmation:</html> +  button.activate=Activate  button.change=Change -button.unblock=Unblock
\ No newline at end of file +button.unblock=Unblock + +help.activation=help.activation +help.pin.mgmt=help.pin.mgmt + +err.activate=<html>An error occured during activation of {0}.</html> +err.change=<html>An error occured during changing of {0}.</html> +err.unblock=<html>Unblocking of {0} is not supported.</html> + +status.not.active=Not active +status.active=Active +status.blocked=Blocked +status.unknown=Unknown diff --git a/BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java b/BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java index 669a63fc..ef8c87e4 100644 --- a/BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java +++ b/BKUAppletExt/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java @@ -25,8 +25,6 @@ import at.gv.egiz.stal.HashDataInput;  import at.gv.egiz.stal.impl.ByteArrayHashDataInput;  import java.awt.event.ActionEvent;  import java.awt.event.ActionListener; -import java.io.ByteArrayInputStream; -import java.io.InputStream;  import java.util.ArrayList;  import java.util.List; @@ -46,7 +44,7 @@ public class BKUGUIWorker implements Runnable {    public void run() {          try { -    final PINSpec signPinSpec = new PINSpec(6, 10, "[0-9]", "Signatur-PIN"); +    final PINSpec signPinSpec = new PINSpec(6, 10, "[0-9]", "Signatur-PIN", (byte)0x00, null);      final ActionListener cancelListener = new ActionListener() { diff --git a/BKUAppletExt/src/test/resources/appletTest.html b/BKUAppletExt/src/test/resources/appletTest.html index 9add4309..813ee1f0 100644 --- a/BKUAppletExt/src/test/resources/appletTest.html +++ b/BKUAppletExt/src/test/resources/appletTest.html @@ -19,7 +19,7 @@      <center>        <applet code="at.gv.egiz.bku.online.applet.PINManagementApplet.class"                archive="../BKUAppletExt-1.0.2-SNAPSHOT.jar, commons-logging.jar , iaik_jce_me4se.jar" -              width=152 height=145> +              width=270 height=180>                <param name="GuiStyle" value="simple"/>                <param name="Locale" value="ja_JA"/>                <!--param name="Background" value="jar:file:/home/clemens/workspace/mocca/BKUApplet/target/BKUApplet-1.0-SNAPSHOT.jar!/images/help.png"/--> diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java index f564c07a..1d5a2cf4 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/BKUGUIImpl.java @@ -38,9 +38,6 @@ import java.util.Collections;  import java.util.List;  import java.util.Locale;  import java.util.ResourceBundle; -import java.util.logging.Level; -import java.util.logging.Logger; -import javax.swing.CellRendererPane;  import javax.swing.GroupLayout;  import javax.swing.ImageIcon;  import javax.swing.JButton; @@ -51,7 +48,6 @@ import javax.swing.JPanel;  import javax.swing.JPasswordField;  import javax.swing.JScrollPane;  import javax.swing.JTable; -import javax.swing.JTextField;  import javax.swing.LayoutStyle;  import javax.swing.ListSelectionModel;  import javax.swing.SwingUtilities; @@ -1064,7 +1060,9 @@ public class BKUGUIImpl implements BKUGUIFacade {      @Override      public char[] getPin() {          if (pinField != null) { -            return pinField.getPassword(); +          char[] pin = pinField.getPassword(); +          pinField = null; +          return pin;          }          return null;      } diff --git a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java index 2054ae86..87b636f0 100644 --- a/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java +++ b/BKUCommonGUI/src/main/java/at/gv/egiz/bku/gui/PinDocument.java @@ -22,6 +22,7 @@ import java.util.regex.Pattern;  import javax.swing.JButton;  import javax.swing.text.AttributeSet;  import javax.swing.text.BadLocationException; +import javax.swing.text.Document;  import javax.swing.text.PlainDocument;  /** @@ -30,9 +31,10 @@ import javax.swing.text.PlainDocument;   */  class PINDocument extends PlainDocument { -        private PINSpec pinSpec; -        private Pattern pinPattern; -        private JButton enterButton; +        protected PINSpec pinSpec; +        protected Pattern pinPattern; +        protected JButton enterButton; +        protected Document compareTo;          public PINDocument(PINSpec pinSpec, JButton enterButton) {              this.pinSpec = pinSpec; @@ -44,6 +46,11 @@ class PINDocument extends PlainDocument {              this.enterButton = enterButton;          } +        public PINDocument(PINSpec pinSpec, JButton enterButton, Document compareTo) { +          this(pinSpec, enterButton); +          this.compareTo = compareTo; +        } +          @Override          public void insertString(int offs, String str, AttributeSet a) throws BadLocationException {              if (pinSpec.getMaxLength() < 0 || pinSpec.getMaxLength() >= (getLength() + str.length())) { @@ -58,12 +65,23 @@ class PINDocument extends PlainDocument {                      super.insertString(offs, str, a);                  }              } -            enterButton.setEnabled(getLength() >= pinSpec.getMinLength()); +            if (enterButton != null) { +              enterButton.setEnabled(getLength() >= pinSpec.getMinLength() && compare()); +            }          }          @Override          public void remove(int offs, int len) throws BadLocationException {              super.remove(offs, len); -            enterButton.setEnabled(getLength() >= pinSpec.getMinLength()); +            if (enterButton != null) { +              enterButton.setEnabled(getLength() >= pinSpec.getMinLength() && compare()); +            } +        } + +        private boolean compare() throws BadLocationException { +          if (compareTo == null) { +            return true; +          } +          return compareTo.getText(0, compareTo.getLength()).equals(getText(0, getLength()));          }      }
\ No newline at end of file diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties index 8436a730..1e0bc9f5 100644 --- a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties +++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties @@ -20,7 +20,7 @@ title.cardnotsupported=<html>Die Karte wird nicht unterst\u00FCtzt</html>  title.cardpin=<html>Karte wird gelesen</html>  title.sign=<html>Signatur erstellen</html>  title.error=<html>Fehler</html> -title.retry=<html>Falscher PIN</html> +title.retry=<html>Falsche PIN</html>  title.wait=<html>Bitte warten</html>  title.hashdata=<html>Signaturdaten</html>  windowtitle.save=Signaturdaten speichern @@ -84,7 +84,7 @@ help.cardnotsupported=Nicht unterst\u00FCtzte B\u00FCrgerkarte  help.insertcard=Keine B\u00FCrgerkarte im Kartenleser  help.cardpin=Pineingabe  help.signpin=Signatur-Pineingabe -help.retry=Falscher Pin +help.retry=Falsche Pin  help.hashdata=Signierte Inhalte  help.hashdatalist=Signierte Inhalte  help.hashdataviewer=Anzeige signierter Inhalte
\ No newline at end of file diff --git a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java index 73aaab46..08ecaa7f 100644 --- a/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java +++ b/BKUCommonGUI/src/test/java/at/gv/egiz/bku/gui/BKUGUIWorker.java @@ -46,7 +46,7 @@ public class BKUGUIWorker implements Runnable {    public void run() {  //        try { -    final PINSpec signPinSpec = new PINSpec(6, 10, "[0-9]", "Signatur-PIN"); +    final PINSpec signPinSpec = new PINSpec(6, 10, "[0-9]", "Signatur-PIN", (byte) 0x81, null);      final ActionListener cancelListener = new ActionListener() { diff --git a/STALExt/src/main/java/at/gv/egiz/stal/ext/ActivatePINRequest.java b/STALExt/src/main/java/at/gv/egiz/stal/ext/PINManagementRequest.java index f2039388..87c53e24 100644 --- a/STALExt/src/main/java/at/gv/egiz/stal/ext/ActivatePINRequest.java +++ b/STALExt/src/main/java/at/gv/egiz/stal/ext/PINManagementRequest.java @@ -20,9 +20,12 @@ package at.gv.egiz.stal.ext;  import at.gv.egiz.stal.STALRequest;  /** + * Dummy STAL request to trigger PIN Management. (no proper STAL requests + * for PIN activation, unblocking) + *   *   * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>   */ -public class ActivatePINRequest extends STALRequest { +public class PINManagementRequest extends STALRequest {  } diff --git a/STALExt/src/main/java/at/gv/egiz/stal/ext/UnblockPINRequest.java b/STALExt/src/main/java/at/gv/egiz/stal/ext/PINManagementResponse.java index 543de31c..b8b90604 100644 --- a/STALExt/src/main/java/at/gv/egiz/stal/ext/UnblockPINRequest.java +++ b/STALExt/src/main/java/at/gv/egiz/stal/ext/PINManagementResponse.java @@ -17,12 +17,12 @@  package at.gv.egiz.stal.ext; -import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.stal.STALResponse;  /**   *   * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>   */ -public class UnblockPINRequest extends STALRequest { +public class PINManagementResponse extends STALResponse {  } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/DataObject.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/DataObject.java index ae4918ce..b64306aa 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/DataObject.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/DataObject.java @@ -14,98 +14,105 @@  * See the License for the specific language governing permissions and  * limitations under the License.  */ -package at.gv.egiz.bku.slcommands.impl.xsect;
 -
 -import iaik.xml.crypto.dom.DOMCryptoContext;
 -
 -import java.io.ByteArrayInputStream;
 -import java.io.ByteArrayOutputStream;
 -import java.io.IOException;
 -import java.io.InputStream;
 -import java.io.SequenceInputStream;
 -import java.io.StringWriter;
 -import java.io.UnsupportedEncodingException;
 -import java.net.URISyntaxException;
 -import java.nio.charset.Charset;
 -import java.security.InvalidAlgorithmParameterException;
 -import java.security.NoSuchAlgorithmException;
 -import java.util.ArrayList;
 +package at.gv.egiz.bku.slcommands.impl.xsect; + +import iaik.xml.crypto.dom.DOMCryptoContext; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.SequenceInputStream; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.net.URISyntaxException; +import java.nio.charset.Charset; +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; +import java.util.ArrayList;  import java.util.Arrays; -import java.util.Collections;
 -import java.util.HashMap;
 -import java.util.List;
 -import java.util.Map;
 -
 -import javax.xml.crypto.MarshalException;
 -import javax.xml.crypto.dom.DOMStructure;
 -import javax.xml.crypto.dsig.CanonicalizationMethod;
 -import javax.xml.crypto.dsig.DigestMethod;
 -import javax.xml.crypto.dsig.Reference;
 -import javax.xml.crypto.dsig.Transform;
 -import javax.xml.crypto.dsig.XMLObject;
 -import javax.xml.crypto.dsig.spec.TransformParameterSpec;
 -import javax.xml.crypto.dsig.spec.XPathFilter2ParameterSpec;
 -import javax.xml.crypto.dsig.spec.XPathType;
 -
 -import org.apache.commons.logging.Log;
 -import org.apache.commons.logging.LogFactory;
 -import org.w3c.dom.DOMConfiguration;
 -import org.w3c.dom.DOMException;
 -import org.w3c.dom.Document;
 -import org.w3c.dom.DocumentFragment;
 -import org.w3c.dom.Element;
 -import org.w3c.dom.Node;
 -import org.w3c.dom.Text;
 -import org.w3c.dom.bootstrap.DOMImplementationRegistry;
 -import org.w3c.dom.ls.DOMImplementationLS;
 -import org.w3c.dom.ls.LSException;
 -import org.w3c.dom.ls.LSInput;
 -import org.w3c.dom.ls.LSOutput;
 -import org.w3c.dom.ls.LSParser;
 -import org.w3c.dom.ls.LSSerializer;
 -
 -import at.buergerkarte.namespaces.securitylayer._1.Base64XMLLocRefOptRefContentType;
 -import at.buergerkarte.namespaces.securitylayer._1.DataObjectInfoType;
 -import at.buergerkarte.namespaces.securitylayer._1.MetaInfoType;
 -import at.buergerkarte.namespaces.securitylayer._1.TransformsInfoType;
 -import at.gv.egiz.bku.binding.HttpUtil;
 -import at.gv.egiz.bku.slexceptions.SLCommandException;
 -import at.gv.egiz.bku.slexceptions.SLRequestException;
 -import at.gv.egiz.bku.slexceptions.SLRuntimeException;
 +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.crypto.MarshalException; +import javax.xml.crypto.dom.DOMStructure; +import javax.xml.crypto.dsig.CanonicalizationMethod; +import javax.xml.crypto.dsig.DigestMethod; +import javax.xml.crypto.dsig.Reference; +import javax.xml.crypto.dsig.Transform; +import javax.xml.crypto.dsig.XMLObject; +import javax.xml.crypto.dsig.spec.TransformParameterSpec; +import javax.xml.crypto.dsig.spec.XPathFilter2ParameterSpec; +import javax.xml.crypto.dsig.spec.XPathType; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3._2000._09.xmldsig_.TransformType; +import org.w3._2000._09.xmldsig_.TransformsType; +import org.w3c.dom.DOMConfiguration; +import org.w3c.dom.DOMException; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentFragment; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.Text; +import org.w3c.dom.bootstrap.DOMImplementationRegistry; +import org.w3c.dom.ls.DOMImplementationLS; +import org.w3c.dom.ls.LSException; +import org.w3c.dom.ls.LSInput; +import org.w3c.dom.ls.LSOutput; +import org.w3c.dom.ls.LSParser; +import org.w3c.dom.ls.LSSerializer; + +import at.buergerkarte.namespaces.securitylayer._1.Base64XMLLocRefOptRefContentType; +import at.buergerkarte.namespaces.securitylayer._1.DataObjectInfoType; +import at.buergerkarte.namespaces.securitylayer._1.MetaInfoType; +import at.buergerkarte.namespaces.securitylayer._1.TransformsInfoType; +import at.gv.egiz.bku.binding.HttpUtil; +import at.gv.egiz.bku.slexceptions.SLCommandException; +import at.gv.egiz.bku.slexceptions.SLRequestException; +import at.gv.egiz.bku.slexceptions.SLRuntimeException;  import at.gv.egiz.bku.slexceptions.SLViewerException; -import at.gv.egiz.bku.utils.urldereferencer.StreamData;
 -import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer;
 +import at.gv.egiz.bku.utils.urldereferencer.StreamData; +import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer;  import at.gv.egiz.bku.viewer.ValidationException;  import at.gv.egiz.bku.viewer.Validator;  import at.gv.egiz.bku.viewer.ValidatorFactory; -import at.gv.egiz.dom.DOMUtils;
 -import at.gv.egiz.slbinding.impl.XMLContentType;
 -
 -/**
 - * This class represents a <code>DataObject</code> of an XML-Signature
 - * created by the security layer command <code>CreateXMLSignature</code>.
 - * 
 - * @author mcentner
 - */
 -public class DataObject {
 -
 -  /**
 -   * Logging facility.
 -   */
 -  private static Log log = LogFactory.getLog(DataObject.class);
 -  
 -  /**
 -   * DOM Implementation.
 -   */
 -  private static final String DOM_LS_3_0 = "LS 3.0";
 -
 -  /**
 -   * The array of the default preferred MIME type order.
 -   */
 -  private static final String[] DEFAULT_PREFFERED_MIME_TYPES = 
 -    new String[] {
 +import at.gv.egiz.dom.DOMUtils; +import at.gv.egiz.marshal.NamespacePrefix; +import at.gv.egiz.marshal.NamespacePrefixMapperImpl; +import at.gv.egiz.slbinding.impl.XMLContentType; +import javax.xml.namespace.NamespaceContext; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; + +/** + * This class represents a <code>DataObject</code> of an XML-Signature + * created by the security layer command <code>CreateXMLSignature</code>. + *  + * @author mcentner + */ +public class DataObject { + +  /** +   * Logging facility. +   */ +  private static Log log = LogFactory.getLog(DataObject.class); +   +  /** +   * DOM Implementation. +   */ +  private static final String DOM_LS_3_0 = "LS 3.0"; + +  /** +   * The array of the default preferred MIME type order. +   */ +  private static final String[] DEFAULT_PREFFERED_MIME_TYPES =  +    new String[] {        "text/plain", -      "application/xhtml+xml" 
 +      "application/xhtml+xml"       };    /** @@ -149,87 +156,87 @@ public class DataObject {      validMimeTypes = mediaTypes;    } -  /**
 -   * The DOM implementation used.
 -   */
 -  private DOMImplementationLS domImplLS;
 -
 -  /**
 -   * The signature context.
 -   */
 -  private SignatureContext ctx;
 -  
 -  /**
 -   * The Reference for this DataObject.
 -   */
 -  private XSECTReference reference;
 -  
 -  /**
 -   * The XMLObject for this DataObject.
 -   */
 -  private XMLObject xmlObject;
 -  
 -  /**
 -   * The MIME-Type of the digest input.
 -   */
 -  private String mimeType;
 -  
 -  /**
 -   * An optional description of the digest input.
 -   */
 -  private String description;
 -  
 -  /**
 -   * Creates a new instance.
 -   * 
 -   * @param document the document of the target signature
 -   */
 -  public DataObject(SignatureContext signatureContext) {
 -    this.ctx = signatureContext;
 -    
 -    DOMImplementationRegistry registry;
 -    try {
 -      registry = DOMImplementationRegistry.newInstance();
 -    } catch (Exception e) {
 -      log.error("Failed to get DOMImplementationRegistry.", e);
 -      throw new SLRuntimeException("Failed to get DOMImplementationRegistry.");
 -    }
 -
 -    domImplLS = (DOMImplementationLS) registry.getDOMImplementation(DOM_LS_3_0);
 -    if (domImplLS == null) {
 -      log.error("Failed to get DOMImplementation " + DOM_LS_3_0);
 -      throw new SLRuntimeException("Failed to get DOMImplementation " + DOM_LS_3_0);
 -    }
 -
 -  }
 -
 -  /**
 -   * @return the reference
 -   */
 -  public Reference getReference() {
 -    return reference;
 -  }
 -
 -  /**
 -   * @return the xmlObject
 -   */
 -  public XMLObject getXmlObject() {
 -    return xmlObject;
 -  }
 -
 -  /**
 -   * @return the mimeType
 -   */
 -  public String getMimeType() {
 -    return mimeType;
 -  }
 -
 -  /**
 -   * @return the description
 -   */
 -  public String getDescription() {
 -    return description;
 -  }
 +  /** +   * The DOM implementation used. +   */ +  private DOMImplementationLS domImplLS; + +  /** +   * The signature context. +   */ +  private SignatureContext ctx; +   +  /** +   * The Reference for this DataObject. +   */ +  private XSECTReference reference; +   +  /** +   * The XMLObject for this DataObject. +   */ +  private XMLObject xmlObject; +   +  /** +   * The MIME-Type of the digest input. +   */ +  private String mimeType; +   +  /** +   * An optional description of the digest input. +   */ +  private String description; +   +  /** +   * Creates a new instance. +   *  +   * @param document the document of the target signature +   */ +  public DataObject(SignatureContext signatureContext) { +    this.ctx = signatureContext; +     +    DOMImplementationRegistry registry; +    try { +      registry = DOMImplementationRegistry.newInstance(); +    } catch (Exception e) { +      log.error("Failed to get DOMImplementationRegistry.", e); +      throw new SLRuntimeException("Failed to get DOMImplementationRegistry."); +    } + +    domImplLS = (DOMImplementationLS) registry.getDOMImplementation(DOM_LS_3_0); +    if (domImplLS == null) { +      log.error("Failed to get DOMImplementation " + DOM_LS_3_0); +      throw new SLRuntimeException("Failed to get DOMImplementation " + DOM_LS_3_0); +    } + +  } + +  /** +   * @return the reference +   */ +  public Reference getReference() { +    return reference; +  } + +  /** +   * @return the xmlObject +   */ +  public XMLObject getXmlObject() { +    return xmlObject; +  } + +  /** +   * @return the mimeType +   */ +  public String getMimeType() { +    return mimeType; +  } + +  /** +   * @return the description +   */ +  public String getDescription() { +    return description; +  }    public void validateHashDataInput() throws SLViewerException { @@ -293,823 +300,920 @@ public class DataObject {      }    } -  
 -  /**
 -   * Configures this DataObject with the information provided within the given
 -   * <code>sl:DataObjectInfo</code>.
 -   * 
 -   * @param dataObjectInfo
 -   *          the <code>sl:DataObjectInfo</code>
 -   * 
 -   * @throws SLCommandException
 -   *           if configuring this DataObject with the information provided in
 -   *           the <code>sl:DataObjectInfo</code> fails.
 -   * @throws SLRequestException
 -   *           if the information provided in the <code>sl:DataObjectInfo</code>
 -   *           does not conform to the security layer specification.
 -   * @throws NullPointerException
 -   *           if <code>dataObjectInfo</code> is <code>null</code>
 -   */
 -  public void setDataObjectInfo(DataObjectInfoType dataObjectInfo) throws SLCommandException, SLRequestException {
 -  
 -    Base64XMLLocRefOptRefContentType dataObject = dataObjectInfo.getDataObject();
 -    String structure = dataObjectInfo.getStructure();
 -    
 -    // select and unmarshal an appropriate transformation path if provided
 -    // and set the final data meta information
 -    XSECTTransforms transforms = createTransformsAndSetFinalDataMetaInfo(dataObjectInfo.getTransformsInfo());
 -  
 -    if ("enveloping".equals(structure)) {
 -      
 -      // configure this DataObject as an enveloped DataObject
 -      setEnvelopedDataObject(dataObject, transforms);
 -      
 -    } else if ("detached".equals(structure)) {
 -      
 -      // configure this DataObject as an detached DataObject
 -      setDetachedDataObject(dataObject, transforms);
 -      
 -    } 
 -    // other values are not allowed by the schema and are therefore ignored
 -    
 -  }
 -
 -  /**
 -   * Configures this DataObject as an enveloped DataObject with the information
 -   * provided within the given <code>sl:DataObject</code>.
 -   * 
 -   * @param dataObject
 -   *          the <code>sl:DataObject</code>
 -   * @param transforms
 -   *          an optional <code>Transforms</code> element (may be
 -   *          <code>null</code>)
 -   * 
 -   * @throws SLCommandException
 -   *           if configuring this DataObject with the information provided in
 -   *           the <code>sl:DataObject</code> fails.
 -   * @throws SLRequestException
 -   *           if the information provided in the <code>sl:DataObject</code>
 -   *           does not conform to the security layer specification.
 -   * @throws NullPointerException
 -   *           if <code>dataObject</code> is <code>null</code>
 -   */
 -  private void setEnvelopedDataObject(
 -      Base64XMLLocRefOptRefContentType dataObject, XSECTTransforms transforms)
 -      throws SLCommandException, SLRequestException {
 -    
 -    String reference = dataObject.getReference();
 -    if (reference == null) {
 -      //
 -      // case A
 -      //
 -      // The Reference attribute is not used; the content of sl:DataObject represents the data object. 
 -      // If the data object is XML-coded (the sl:XMLContent element is used in sl:DataObject), then it 
 -      // must be incorporated in the signature structure as parsed XML.
 -      //
 -
 -      if (dataObject.getBase64Content() != null) {
 -
 -        log.debug("Adding DataObject (Base64Content) without a reference URI.");
 -
 -        // create XMLObject
 -        XMLObject xmlObject = createXMLObject(new ByteArrayInputStream(dataObject.getBase64Content()));
 -
 -        setXMLObjectAndReferenceBase64(xmlObject, transforms);
 -        
 -      } else if (dataObject.getXMLContent() != null) {
 -        
 -        log.debug("Adding DataObject (XMLContent) without a reference URI.");
 -
 -        // create XMLObject
 -        DocumentFragment content = parseDataObject((XMLContentType) dataObject.getXMLContent());
 -        XMLObject xmlObject = createXMLObject(content);
 -        
 -        setXMLObjectAndReferenceXML(xmlObject, transforms);
 -        
 -      } else if (dataObject.getLocRefContent() != null) {
 -        
 -        log.debug("Adding DataObject (LocRefContent) without a reference URI.");
 -        
 -        setEnvelopedDataObject(dataObject.getLocRefContent(), transforms);
 -        
 -      } else {
 -        
 -        // not allowed
 -        log.info("XML structure of the command request contains an " +
 -                "invalid combination of optional elements or attributes. " +
 -            "DataObject of structure='enveloped' without a reference must contain content.");
 -        throw new SLRequestException(3003);
 -        
 -      }
 -      
 -    } else {
 -      
 -      if (dataObject.getBase64Content() == null &&
 -          dataObject.getXMLContent() == null &&
 -          dataObject.getLocRefContent() == null) {
 -
 -        //
 -        // case B
 -        //
 -        // The Reference attribute contains a URI that must be resolved by the 
 -        // Citizen Card Environment to obtain the data object. 
 -        // The content of sl:DataObject remains empty
 -        //
 -        
 -        log.debug("Adding DataObject from reference URI '" + reference + "'.");
 -        
 -        setEnvelopedDataObject(reference, transforms);
 -        
 -      } else {
 -        
 -        // not allowed
 -        log.info("XML structure of the command request contains an " +
 -            "invalid combination of optional elements or attributes. " +
 -        "DataObject of structure='enveloped' with reference must not contain content.");
 -        throw new SLRequestException(3003);
 -        
 -      }
 -      
 -      
 -    }
 -    
 -  }
 -
 -  /**
 -   * Configures this DataObject as an enveloped DataObject with the content to
 -   * be dereferenced from the given <code>reference</code>.
 -   * 
 -   * @param reference
 -   *          the <code>reference</code> URI
 -   * @param transforms
 -   *          an optional <code>Transforms</code> element (may be
 -   *          <code>null</code>)
 -   * 
 -   * @throws SLCommandException
 -   *           if dereferencing the given <code>reference</code> fails, or if
 -   *           configuring this DataObject with the data dereferenced from the
 -   *           given <code>reference</code> fails.
 -   * @throws NullPointerException
 -   *           if <code>reference</code> is <code>null</code>
 -   */
 -  private void setEnvelopedDataObject(String reference, XSECTTransforms transforms) throws SLCommandException {
 -
 -    if (reference == null) {
 -      throw new NullPointerException("Argument 'reference' must not be null.");
 -    }
 -    
 -    // dereference URL
 -    URLDereferencer dereferencer = URLDereferencer.getInstance();
 -    
 -    StreamData streamData;
 -    try {
 -      streamData = dereferencer.dereference(reference, ctx.getDereferencerContext());
 -    } catch (IOException e) {
 -      log.info("Failed to dereference XMLObject from '" + reference + "'.", e);
 -      throw new SLCommandException(4110);
 -    }
 -
 -    Node childNode;
 -    
 -    String contentType = streamData.getContentType();
 -    if (contentType.startsWith("text/xml")) {
 -  
 -      // If content type is text/xml parse content.
 -      String charset = HttpUtil.getCharset(contentType, true);
 -      
 -      Document doc = parseDataObject(streamData.getStream(), charset);
 -      
 -      childNode = doc.getDocumentElement();
 -      
 -      if (childNode == null) {
 -        log.info("Failed to parse XMLObject from '" + reference + "'.");
 -        throw new SLCommandException(4111);
 -      }
 -      
 -      XMLObject xmlObject = createXMLObject(childNode);
 -      
 -      setXMLObjectAndReferenceXML(xmlObject, transforms);
 -      
 -    } else {
 -  
 -      // Include content Base64 encoded.
 -      XMLObject xmlObject = createXMLObject(streamData.getStream());
 -      
 -      setXMLObjectAndReferenceBase64(xmlObject, transforms);
 -      
 -    }
 -    
 -  }
 -
 -  /**
 -   * Configures this DataObject as an detached DataObject with the information
 -   * provided in the given <code>sl:DataObject</code> and optionally
 -   * <code>transforms</code>.
 -   * 
 -   * @param dataObject
 -   *          the <code>sl:DataObject</code>
 -   * @param transforms
 -   *          an optional Transforms object, may be <code>null</code>
 -   * 
 -   * @throws SLCommandException
 -   *           if configuring this DataObject with the information provided in
 -   *           the <code>sl:DataObject</code> fails.
 -   * @throws SLRequestException
 -   *           if the information provided in the <code>sl:DataObject</code>
 -   *           does not conform to the security layer specification.
 -   * @throws NullPointerException
 -   *           if <code>dataObject</code> is <code>null</code>
 -   */
 -  private void setDetachedDataObject(
 -      Base64XMLLocRefOptRefContentType dataObject, XSECTTransforms transforms)
 -      throws SLCommandException, SLRequestException {
 -    
 -    String referenceURI = dataObject.getReference();
 -    
 -    if (referenceURI == null) {
 -      
 -      // not allowed
 -      log.info("XML structure of the command request contains an " +
 -          "invalid combination of optional elements or attributes. " +
 -      "DataObject of structure='detached' must contain a reference.");
 -      throw new SLRequestException(3003);
 -
 -    } else {
 -      
 -      DigestMethod dm;
 -      try {
 -        dm = ctx.getAlgorithmMethodFactory().createDigestMethod(ctx);
 -      } catch (NoSuchAlgorithmException e) {
 -        log.error("Failed to get DigestMethod.", e);
 -        throw new SLCommandException(4006);
 -      } catch (InvalidAlgorithmParameterException e) {
 -        log.error("Failed to get DigestMethod.", e);
 -        throw new SLCommandException(4006);
 -      }
 -      
 -      String idValue = ctx.getIdValueFactory().createIdValue("Reference");
 -      
 -      reference = new XSECTReference(referenceURI, dm, transforms, null, idValue);
 -      
 -      // case D:
 -      //
 -      // The Reference attribute contains a URI that is used by the Citizen Card
 -      // Environment to code the reference to the data object as part of the XML
 -      // signature (attribute URI in the dsig:Reference) element. The content of
 -      // sl:DataObject represents the data object.
 -      
 -      if (dataObject.getLocRefContent() != null) {
 -        String locRef = dataObject.getLocRefContent();
 -        try {
 -          this.reference.setDereferencer(new LocRefDereferencer(ctx.getDereferencerContext(), locRef));
 -        } catch (URISyntaxException e) {
 -          log.info("Invalid URI '" + locRef + "' in DataObject.", e);
 -          throw new SLCommandException(4003);
 -        } catch (IllegalArgumentException e) {
 -          log.info("LocRef URI of '" + locRef + "' not supported in DataObject. ", e);
 -          throw new SLCommandException(4003);
 -        }
 -      } else if (dataObject.getBase64Content() != null) {
 -        byte[] base64Content = dataObject.getBase64Content();
 -        this.reference.setDereferencer(new ByteArrayDereferencer(base64Content));
 -      } else if (dataObject.getXMLContent() != null) {
 -        XMLContentType xmlContent = (XMLContentType) dataObject.getXMLContent();
 -        byte[] bytes = xmlContent.getRedirectedStream().toByteArray();
 -        this.reference.setDereferencer(new ByteArrayDereferencer(bytes));
 -      } else {
 -        
 -        // case C:
 -        //
 -        // The Reference attribute contains a URI that must be resolved by the
 -        // Citizen Card Environment to obtain the data object. The Reference
 -        // attribute contains a URI that is used by the Citizen Card Environment
 -        // to code the reference to the data object as part of the XML signature
 -        // (attribute URI in the dsig:Reference) element. The content of
 -        // sl:DataObject remains empty.
 -
 -      }
 -      
 -    }     
 -  }
 -
 -  /**
 -   * Returns the preferred <code>sl:TransformInfo</code> from the given list of
 -   * <code>transformInfos</code>, or <code>null</code> if none of the given
 -   * <code>transformInfos</code> is preferred over the others.
 -   * 
 -   * @param transformsInfos
 -   *          a list of <code>sl:TransformInfo</code>s
 -   * 
 -   * @return the selected <code>sl:TransformInfo</code> or <code>null</code>, if
 -   *         none is preferred over the others
 -   */
 -  private TransformsInfoType selectPreferredTransformsInfo(List<TransformsInfoType> transformsInfos) {
 -    
 -    Map<String, TransformsInfoType> mimeTypes = new HashMap<String, TransformsInfoType>();
 -    
 -    StringBuilder debugString = null;
 -    if (log.isDebugEnabled()) {
 -      debugString = new StringBuilder();
 -      debugString.append("Got " + transformsInfos.size() + " TransformsInfo(s):");
 -    }
 -    
 -    for (TransformsInfoType transformsInfoType : transformsInfos) {
 -      MetaInfoType finalDataMetaInfo = transformsInfoType.getFinalDataMetaInfo();
 -      String mimeType = finalDataMetaInfo.getMimeType();
 -      String description = finalDataMetaInfo.getDescription();
 -      mimeTypes.put(mimeType, transformsInfoType);
 -      if (debugString != null) {
 -        debugString.append("\n FinalDataMetaInfo: MIME-Type=");
 -        debugString.append(mimeType);
 -        if (description != null) {
 -          debugString.append(" ");
 -          debugString.append(description);
 -        }
 -      }
 -    }
 -
 -    if (debugString != null) {
 -      log.debug(debugString);
 -    }
 -
 -    // look for preferred transform
 -    for (String mimeType : DEFAULT_PREFFERED_MIME_TYPES) {
 -      if (mimeTypes.containsKey(mimeType)) {
 -        return mimeTypes.get(mimeType);
 -      }
 -    }
 -    
 -    // no preferred transform
 -    return null;
 -    
 -  }
 -
 -  /**
 -   * Create an instance of <code>ds:Transforms</code> from the given
 -   * <code>sl:TransformsInfo</code>.
 -   * 
 -   * @param transformsInfo
 -   *          the <code>sl:TransformsInfo</code>
 -   * 
 -   * @return a corresponding unmarshalled <code>ds:Transforms</code>, or
 -   *         <code>null</code> if the given <code>sl:TransformsInfo</code> does
 -   *         not contain a <code>dsig:Transforms</code> element
 -   * 
 -   * @throws SLRequestException
 -   *           if the <code>ds:Transforms</code> in the given
 -   *           <code>transformsInfo</code> are not valid or cannot be parsed.
 -   * 
 -   * @throws MarshalException
 -   *           if the <code>ds:Transforms</code> in the given
 -   *           <code>transformsInfo</code> cannot be unmarshalled.
 -   */
 -  private XSECTTransforms createTransforms(TransformsInfoType transformsInfo) throws SLRequestException, MarshalException {
 -    
 -    ByteArrayOutputStream redirectedStream = ((at.gv.egiz.slbinding.impl.TransformsInfoType) transformsInfo).getRedirectedStream();
 -    byte[] transformBytes = (redirectedStream != null) ? redirectedStream.toByteArray() : null;
 -    
 -    if (transformBytes != null && transformBytes.length > 0) {
 -
 -      // debug
 -      if (log.isTraceEnabled()) {
 -        StringBuilder sb = new StringBuilder();
 -        sb.append("Trying to parse transforms:\n");
 -        sb.append(new String(transformBytes, Charset.forName("UTF-8")));
 -        log.trace(sb);
 -      }
 -      
 -      DOMImplementationLS domImplLS = DOMUtils.getDOMImplementationLS();
 -      LSInput input = domImplLS.createLSInput();
 -      input.setByteStream(new ByteArrayInputStream(transformBytes));
 -
 -      LSParser parser = domImplLS.createLSParser(
 -          DOMImplementationLS.MODE_SYNCHRONOUS, null);
 -      DOMConfiguration domConfig = parser.getDomConfig();
 -      SimpleDOMErrorHandler errorHandler = new SimpleDOMErrorHandler();
 -      domConfig.setParameter("error-handler", errorHandler);
 -      domConfig.setParameter("validate", Boolean.FALSE);
 -
 -      Document document;
 -      try {
 -        document = parser.parse(input);
 -      } catch (DOMException e) {
 -        log.info("Failed to parse dsig:Transforms.", e);
 -        throw new SLRequestException(3002);
 -      } catch (LSException e) {
 -        log.info("Failed to parse dsig:Transforms.", e);
 -        throw new SLRequestException(3002);
 -      }
 -
 -      // adopt ds:Transforms
 -      Element documentElement = document.getDocumentElement();
 -      Node adoptedTransforms = ctx.getDocument().adoptNode(documentElement);
 -
 -      DOMCryptoContext context = new DOMCryptoContext();
 -
 -      // unmarshall ds:Transforms
 -      return new XSECTTransforms(context, adoptedTransforms);
 -
 -    } else {
 -      return null;
 -    }
 -    
 -  }
 -  
 -  /**
 -   * Sets the <code>mimeType</code> and the <code>description</code> value
 -   * for this DataObject.
 -   * 
 -   * @param metaInfoType the <code>sl:FinalMetaDataInfo</code>
 -   * 
 -   * @throws NullPointerException if <code>metaInfoType</code> is <code>null</code>
 -   */
 -  private void setFinalDataMetaInfo(MetaInfoType metaInfoType) {
 -    
 -    this.mimeType = metaInfoType.getMimeType();
 -    this.description = metaInfoType.getDescription();
 -    
 -  }
 -  
 -  /**
 -   * Selects an appropriate transformation path (if present) from the given list
 -   * of <code>sl:TransformInfos</code>, sets the corresponding final data meta info and
 -   * returns the corresponding unmarshalled <code>ds:Transforms</code>.
 -   * 
 -   * @param transformsInfos the <code>sl:TransformInfos</code>
 -   * 
 -   * @return the unmarshalled <code>ds:Transforms</code>, or <code>null</code> if
 -   * no transformation path has been selected.
 -   * 
 -   * @throws SLRequestException if the given list <code>ds:TransformsInfo</code> contains
 -   * an invalid <code>ds:Transforms</code> element, or no suitable transformation path
 -   * can be found. 
 -   */
 -  private XSECTTransforms createTransformsAndSetFinalDataMetaInfo(
 -      List<TransformsInfoType> transformsInfos) throws SLRequestException {
 -
 -    TransformsInfoType preferredTransformsInfo = selectPreferredTransformsInfo(transformsInfos);
 -    // try preferred transform
 -    if (preferredTransformsInfo != null) {
 -
 -      try {
 -        XSECTTransforms transforms = createTransforms(preferredTransformsInfo);
 -        setFinalDataMetaInfo(preferredTransformsInfo.getFinalDataMetaInfo());
 -        return transforms;
 -      } catch (MarshalException e) {
 -      
 -        String mimeType = preferredTransformsInfo.getFinalDataMetaInfo().getMimeType();
 -        log.info("Failed to unmarshal preferred transformation path (MIME-Type="
 -            + mimeType + ").", e);
 -      
 -      }
 -
 -    }
 -
 -    // look for another suitable transformation path
 -    for (TransformsInfoType transformsInfoType : transformsInfos) {
 -      
 -      try {
 -        XSECTTransforms transforms = createTransforms(transformsInfoType);
 -        setFinalDataMetaInfo(transformsInfoType.getFinalDataMetaInfo());
 -        return transforms;
 -      } catch (MarshalException e) {
 -
 -        String mimeType = transformsInfoType.getFinalDataMetaInfo().getMimeType();
 -        log.info("Failed to unmarshal transformation path (MIME-Type="
 -            + mimeType + ").", e);
 -      }
 -      
 -    }
 -
 -    // no suitable transformation path found
 -    throw new SLRequestException(3003);
 -    
 -  }
 -
 -  /**
 -   * Create an XMLObject with the Base64 encoding of the given
 -   * <code>content</code>.
 -   * 
 -   * @param content
 -   *          the to-be Base64 encoded content
 -   * @return an XMLObject with the Base64 encoded <code>content</code>
 -   */
 -  private XMLObject createXMLObject(InputStream content) {
 -    
 -    Text textNode;
 -    try {
 -      textNode = at.gv.egiz.dom.DOMUtils.createBase64Text(content, ctx.getDocument());
 -    } catch (IOException e) {
 -      log.error(e);
 -      throw new SLRuntimeException(e);
 -    }
 -
 -    DOMStructure structure = new DOMStructure(textNode);
 -    
 -    String idValue = ctx.getIdValueFactory().createIdValue("Object");
 -
 -    return ctx.getSignatureFactory().newXMLObject(Collections.singletonList(structure), idValue, null, null);
 -    
 -  }
 -  
 -  /**
 -   * Create an XMLObject with the given <code>content</code> node.
 -   * 
 -   * @param content the content node
 -   * 
 -   * @return an XMLObject with the given <code>content</code>
 -   */
 -  private XMLObject createXMLObject(Node content) {
 -    
 -    String idValue = ctx.getIdValueFactory().createIdValue("Object");
 -    
 -    List<DOMStructure> structures = Collections.singletonList(new DOMStructure(content));
 -    
 -    return ctx.getSignatureFactory().newXMLObject(structures, idValue, null, null);
 -    
 -  }
 -
 -  /**
 -   * Sets the given <code>xmlObject</code> and creates and sets a corresponding
 -   * <code>Reference</code>.
 -   * <p>
 -   * A transform to Base64-decode the xmlObject's content is inserted at the top
 -   * of to the optional <code>transforms</code> if given, or to a newly created
 -   * <code>Transforms</code> element if <code>transforms</code> is
 -   * <code>null</code>.
 -   * 
 -   * @param xmlObject
 -   *          the XMLObject
 -   * @param transforms
 -   *          an optional <code>Transforms</code> element (may be
 -   *          <code>null</code>)
 -   * 
 -   * @throws SLCommandException
 -   *           if creating the Reference fails
 -   * @throws NullPointerException
 -   *           if <code>xmlObject</code> is <code>null</code>
 -   */
 -  private void setXMLObjectAndReferenceBase64(XMLObject xmlObject, XSECTTransforms transforms) throws SLCommandException {
 -    
 -    // create reference URI
 -    //
 -    // NOTE: the ds:Object can be referenced directly, as the Base64 transform
 -    // operates on the text() of the input nodelist.
 -    //
 -    String referenceURI = "#" + xmlObject.getId();
 -  
 -    // create Base64 Transform
 -    Transform transform;
 -    try {
 -      transform = ctx.getSignatureFactory().newTransform(Transform.BASE64, (TransformParameterSpec) null);
 -    } catch (NoSuchAlgorithmException e) {
 -      // algorithm must be present
 -      throw new SLRuntimeException(e);
 -    } catch (InvalidAlgorithmParameterException e) {
 -      // algorithm does not take parameters
 -      throw new SLRuntimeException(e);
 -    }
 -    
 -    if (transforms == null) {
 -      transforms = new XSECTTransforms(Collections.singletonList(transform)); 
 -    } else {
 -      transforms.insertTransform(transform);
 -    }
 -  
 -    DigestMethod dm;
 -    try {
 -      dm = ctx.getAlgorithmMethodFactory().createDigestMethod(ctx);
 -    } catch (NoSuchAlgorithmException e) {
 -      log.error("Failed to get DigestMethod.", e);
 -      throw new SLCommandException(4006);
 -    } catch (InvalidAlgorithmParameterException e) {
 -      log.error("Failed to get DigestMethod.", e);
 -      throw new SLCommandException(4006);
 -    }
 -    String id = ctx.getIdValueFactory().createIdValue("Reference");
 -    
 -    this.xmlObject = xmlObject;
 -    this.reference = new XSECTReference(referenceURI, dm, transforms, null, id);
 -    
 -  }
 -
 -  /**
 -   * Sets the given <code>xmlObject</code> and creates and sets a corresponding
 -   * <code>Reference</code>.
 -   * <p>
 -   * A transform to select the xmlObject's content is inserted at the top of to
 -   * the optional <code>transforms</code> if given, or to a newly created
 -   * <code>Transforms</code> element if <code>transforms</code> is
 -   * <code>null</code>.
 -   * </p>
 -   * 
 -   * @param xmlObject
 -   *          the XMLObject
 -   * @param transforms
 -   *          an optional <code>Transforms</code> element (may be
 -   *          <code>null</code>)
 -   * 
 -   * @throws SLCommandException
 -   *           if creating the Reference fails
 -   * @throws NullPointerException
 -   *           if <code>xmlObject</code> is <code>null</code>
 -   */
 -  private void setXMLObjectAndReferenceXML(XMLObject xmlObject, XSECTTransforms transforms) throws SLCommandException {
 -    
 -    // create reference URI
 -    String referenceURI = "#" + xmlObject.getId();
 -    
 -    // create Transform to select ds:Object's children
 -    Transform xpathTransform;
 -    Transform c14nTransform;
 -    try {
 -
 -      XPathType xpath = new XPathType("id(\"" + xmlObject.getId() + "\")/node()", XPathType.Filter.INTERSECT);
 -      List<XPathType> xpaths = Collections.singletonList(xpath);
 -      XPathFilter2ParameterSpec params = new XPathFilter2ParameterSpec(xpaths);
 -
 -      xpathTransform = ctx.getSignatureFactory().newTransform(Transform.XPATH2, params);
 -
 -      // add exclusive canonicalization to avoid signing the namespace context of the ds:Object
 -      c14nTransform = ctx.getSignatureFactory().newTransform(CanonicalizationMethod.EXCLUSIVE, (TransformParameterSpec) null);
 -      
 -    } catch (NoSuchAlgorithmException e) {
 -      // algorithm must be present
 -      throw new SLRuntimeException(e);
 -    } catch (InvalidAlgorithmParameterException e) {
 -      // params must be appropriate
 -      throw new SLRuntimeException(e);
 -    }
 -  
 -    if (transforms == null) {
 -      List<Transform> newTransfroms = new ArrayList<Transform>();
 -      newTransfroms.add(xpathTransform);
 -      newTransfroms.add(c14nTransform);
 -      transforms = new XSECTTransforms(newTransfroms);
 -    } else {
 -      transforms.insertTransform(xpathTransform);
 -    }
 -    
 -    DigestMethod dm;
 -    try {
 -      dm = ctx.getAlgorithmMethodFactory().createDigestMethod(ctx);
 -    } catch (NoSuchAlgorithmException e) {
 -      log.error("Failed to get DigestMethod.", e);
 -      throw new SLCommandException(4006);
 -    } catch (InvalidAlgorithmParameterException e) {
 -      log.error("Failed to get DigestMethod.", e);
 -      throw new SLCommandException(4006);
 -    }
 -    String id = ctx.getIdValueFactory().createIdValue("Reference");
 -
 -    this.xmlObject = xmlObject;
 -    this.reference = new XSECTReference(referenceURI, dm, transforms, null, id);
 -    
 -  }
 -
 -  /**
 -   * Parses the given <code>xmlContent</code> and returns a corresponding
 -   * document fragment.
 -   * 
 -   * <p>
 -   * The to-be parsed content is surrounded by <dummy> ... </dummy> elements to
 -   * allow for mixed (e.g. Text and Element) content in XMLContent.
 -   * </p>
 -   * 
 -   * @param xmlContent
 -   *          the XMLContent to-be parsed
 -   * 
 -   * @return a document fragment containing the parsed nodes
 -   * 
 -   * @throws SLCommandException
 -   *           if parsing the given <code>xmlContent</code> fails
 -   * 
 -   * @throws NullPointerException
 -   *           if <code>xmlContent</code> is <code>null</code>
 -   */
 -  private DocumentFragment parseDataObject(XMLContentType xmlContent) throws SLCommandException {
 -    
 -    ByteArrayOutputStream redirectedStream =  xmlContent.getRedirectedStream();
 -  
 -    // Note: We can assume a fixed character encoding of UTF-8 for the
 -    // content of the redirect stream as the content has already been parsed
 -    // and serialized again to the redirect stream.
 -    
 -    List<InputStream> inputStreams = new ArrayList<InputStream>();
 -    try {
 -      // dummy start element
 -      inputStreams.add(new ByteArrayInputStream("<dummy>".getBytes("UTF-8")));
 -  
 -      // content
 -      inputStreams.add(new ByteArrayInputStream(redirectedStream.toByteArray()));
 -      
 -      // dummy end element
 -      inputStreams.add(new ByteArrayInputStream("</dummy>".getBytes("UTF-8")));
 -    } catch (UnsupportedEncodingException e) {
 -      throw new SLRuntimeException(e);
 -    }
 -    
 -    SequenceInputStream inputStream = new SequenceInputStream(Collections.enumeration(inputStreams));
 -  
 -    // parse DataObject
 -    Document doc = parseDataObject(inputStream, "UTF-8");
 -    
 -    Element documentElement = doc.getDocumentElement();
 -  
 -    if (documentElement == null ||
 -        !"dummy".equals(documentElement.getLocalName())) {
 -      log.info("Failed to parse DataObject XMLContent.");
 -      throw new SLCommandException(4111);
 -    }
 -    
 -    DocumentFragment fragment = doc.createDocumentFragment();
 -    while (documentElement.getFirstChild() != null) {
 -      fragment.appendChild(documentElement.getFirstChild());
 -    }
 -    
 -    // log parsed document
 -    if (log.isTraceEnabled()) {
 -      
 -      StringWriter writer = new StringWriter();
 -      
 -      writer.write("DataObject:\n");
 -      
 -      LSOutput output = domImplLS.createLSOutput();
 -      output.setCharacterStream(writer);
 -      output.setEncoding("UTF-8");
 -      LSSerializer serializer = domImplLS.createLSSerializer();
 -      serializer.getDomConfig().setParameter("xml-declaration", Boolean.FALSE);
 -      serializer.write(fragment, output);
 -      
 -      log.trace(writer.toString());
 -    }
 -    
 -    return fragment;
 -    
 -  }
 -
 -  /**
 -   * Parses the given <code>inputStream</code> using the given
 -   * <code>encoding</code> and returns the parsed document.
 -   * 
 -   * @param inputStream
 -   *          the to-be parsed input
 -   * 
 -   * @param encoding
 -   *          the encoding to be used for parsing the given
 -   *          <code>inputStream</code>
 -   * 
 -   * @return the parsed document
 -   * 
 -   * @throws SLCommandException
 -   *           if parsing the <code>inputStream</code> fails.
 -   * 
 -   * @throws NullPointerException
 -   *           if <code>inputStram</code> is <code>null</code>
 -   */
 -  private Document parseDataObject(InputStream inputStream, String encoding) throws SLCommandException {
 -
 -    LSInput input = domImplLS.createLSInput();
 -    input.setByteStream(inputStream);
 -
 -    if (encoding != null) {
 -      input.setEncoding(encoding);
 -    }
 -    
 -    LSParser parser = domImplLS.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null);
 -    DOMConfiguration domConfig = parser.getDomConfig();
 -    SimpleDOMErrorHandler errorHandler = new SimpleDOMErrorHandler();
 -    domConfig.setParameter("error-handler", errorHandler);
 -    domConfig.setParameter("validate", Boolean.FALSE);
 -
 -    Document doc;
 -    try {
 -      doc = parser.parse(input);
 -    } catch (DOMException e) {
 -      log.info("Existing XML document cannot be parsed.", e);
 -      throw new SLCommandException(4111);
 -    } catch (LSException e) {
 -      log.info("Existing XML document cannot be parsed. ", e);
 -      throw new SLCommandException(4111);
 -    }
 -    
 -    if (errorHandler.hasErrors()) {
 -      // log errors
 -      if (log.isInfoEnabled()) {
 -        List<String> errorMessages = errorHandler.getErrorMessages();
 -        StringBuffer sb = new StringBuffer();
 -        for (String errorMessage : errorMessages) {
 -          sb.append(" ");
 -          sb.append(errorMessage);
 -        }
 -        log.info("Existing XML document cannot be parsed. " + sb.toString());
 -      }
 -      throw new SLCommandException(4111);
 -    }
 -
 -    return doc;
 -    
 -  }
 -
 -
 -}
 +   +  /** +   * Configures this DataObject with the information provided within the given +   * <code>sl:DataObjectInfo</code>. +   *  +   * @param dataObjectInfo +   *          the <code>sl:DataObjectInfo</code> +   *  +   * @throws SLCommandException +   *           if configuring this DataObject with the information provided in +   *           the <code>sl:DataObjectInfo</code> fails. +   * @throws SLRequestException +   *           if the information provided in the <code>sl:DataObjectInfo</code> +   *           does not conform to the security layer specification. +   * @throws NullPointerException +   *           if <code>dataObjectInfo</code> is <code>null</code> +   */ +  public void setDataObjectInfo(DataObjectInfoType dataObjectInfo) throws SLCommandException, SLRequestException { +   +    Base64XMLLocRefOptRefContentType dataObject = dataObjectInfo.getDataObject(); +    String structure = dataObjectInfo.getStructure(); +     +    // select and unmarshal an appropriate transformation path if provided +    // and set the final data meta information +    XSECTTransforms transforms = createTransformsAndSetFinalDataMetaInfo(dataObjectInfo.getTransformsInfo()); +   +    if ("enveloping".equals(structure)) { +       +      // configure this DataObject as an enveloped DataObject +      setEnvelopedDataObject(dataObject, transforms); +       +    } else if ("detached".equals(structure)) { +       +      // configure this DataObject as an detached DataObject +      setDetachedDataObject(dataObject, transforms); +       +    }  +    // other values are not allowed by the schema and are therefore ignored +     +  } + +  private byte[] getTransformsBytes(at.gv.egiz.slbinding.impl.TransformsInfoType ti) { +    return ti.getRedirectedStream().toByteArray(); +//    byte[] transformsBytes = ti.getRedirectedStream().toByteArray(); +// +//    if (transformsBytes == null || transformsBytes.length == 0) { +//      return null; +//    } +// +//    String dsigPrefix = ti.getNamespaceContext().getNamespaceURI("http://www.w3.org/2000/09/xmldsig#"); +//    byte[] pre, post; +//    if (dsigPrefix == null) { +//      log.trace("XMLDSig not declared in outside dsig:Transforms"); +//      pre = "<AssureDSigNS>".getBytes(); +//      post = "</AssureDSigNS>".getBytes(); +//    } else { +//      log.trace("XMLDSig bound to prefix " + dsigPrefix); +//       pre = ("<AssureDSigNS xmlns:" + dsigPrefix + "=\"http://www.w3.org/2000/09/xmldsig#\">").getBytes(); +//       post = "</AssureDSigNS>".getBytes(); +//    } +// +//    byte[] workaround = new byte[pre.length + transformsBytes.length + post.length]; +//    System.arraycopy(pre, 0, workaround, 0, pre.length); +//    System.arraycopy(transformsBytes, 0, workaround, pre.length, transformsBytes.length); +//    System.arraycopy(post, 0, workaround, pre.length + transformsBytes.length, post.length); +//    return workaround; +  } + +  /** +   * Configures this DataObject as an enveloped DataObject with the information +   * provided within the given <code>sl:DataObject</code>. +   *  +   * @param dataObject +   *          the <code>sl:DataObject</code> +   * @param transforms +   *          an optional <code>Transforms</code> element (may be +   *          <code>null</code>) +   *  +   * @throws SLCommandException +   *           if configuring this DataObject with the information provided in +   *           the <code>sl:DataObject</code> fails. +   * @throws SLRequestException +   *           if the information provided in the <code>sl:DataObject</code> +   *           does not conform to the security layer specification. +   * @throws NullPointerException +   *           if <code>dataObject</code> is <code>null</code> +   */ +  private void setEnvelopedDataObject( +      Base64XMLLocRefOptRefContentType dataObject, XSECTTransforms transforms) +      throws SLCommandException, SLRequestException { +     +    String reference = dataObject.getReference(); +    if (reference == null) { +      // +      // case A +      // +      // The Reference attribute is not used; the content of sl:DataObject represents the data object.  +      // If the data object is XML-coded (the sl:XMLContent element is used in sl:DataObject), then it  +      // must be incorporated in the signature structure as parsed XML. +      // + +      if (dataObject.getBase64Content() != null) { + +        log.debug("Adding DataObject (Base64Content) without a reference URI."); + +        // create XMLObject +        XMLObject xmlObject = createXMLObject(new ByteArrayInputStream(dataObject.getBase64Content())); + +        setXMLObjectAndReferenceBase64(xmlObject, transforms); +         +      } else if (dataObject.getXMLContent() != null) { +         +        log.debug("Adding DataObject (XMLContent) without a reference URI."); + +        // create XMLObject +        DocumentFragment content = parseDataObject((XMLContentType) dataObject.getXMLContent()); +        XMLObject xmlObject = createXMLObject(content); +         +        setXMLObjectAndReferenceXML(xmlObject, transforms); +         +      } else if (dataObject.getLocRefContent() != null) { +         +        log.debug("Adding DataObject (LocRefContent) without a reference URI."); +         +        setEnvelopedDataObject(dataObject.getLocRefContent(), transforms); +         +      } else { +         +        // not allowed +        log.info("XML structure of the command request contains an " + +                "invalid combination of optional elements or attributes. " + +            "DataObject of structure='enveloped' without a reference must contain content."); +        throw new SLRequestException(3003); +         +      } +       +    } else { +       +      if (dataObject.getBase64Content() == null && +          dataObject.getXMLContent() == null && +          dataObject.getLocRefContent() == null) { + +        // +        // case B +        // +        // The Reference attribute contains a URI that must be resolved by the  +        // Citizen Card Environment to obtain the data object.  +        // The content of sl:DataObject remains empty +        // +         +        log.debug("Adding DataObject from reference URI '" + reference + "'."); +         +        setEnvelopedDataObject(reference, transforms); +         +      } else { +         +        // not allowed +        log.info("XML structure of the command request contains an " + +            "invalid combination of optional elements or attributes. " + +        "DataObject of structure='enveloped' with reference must not contain content."); +        throw new SLRequestException(3003); +         +      } +       +       +    } +     +  } + +  /** +   * Configures this DataObject as an enveloped DataObject with the content to +   * be dereferenced from the given <code>reference</code>. +   *  +   * @param reference +   *          the <code>reference</code> URI +   * @param transforms +   *          an optional <code>Transforms</code> element (may be +   *          <code>null</code>) +   *  +   * @throws SLCommandException +   *           if dereferencing the given <code>reference</code> fails, or if +   *           configuring this DataObject with the data dereferenced from the +   *           given <code>reference</code> fails. +   * @throws NullPointerException +   *           if <code>reference</code> is <code>null</code> +   */ +  private void setEnvelopedDataObject(String reference, XSECTTransforms transforms) throws SLCommandException { + +    if (reference == null) { +      throw new NullPointerException("Argument 'reference' must not be null."); +    } +     +    // dereference URL +    URLDereferencer dereferencer = URLDereferencer.getInstance(); +     +    StreamData streamData; +    try { +      streamData = dereferencer.dereference(reference, ctx.getDereferencerContext()); +    } catch (IOException e) { +      log.info("Failed to dereference XMLObject from '" + reference + "'.", e); +      throw new SLCommandException(4110); +    } + +    Node childNode; +     +    String contentType = streamData.getContentType(); +    if (contentType.startsWith("text/xml")) { +   +      // If content type is text/xml parse content. +      String charset = HttpUtil.getCharset(contentType, true); +       +      Document doc = parseDataObject(streamData.getStream(), charset); +       +      childNode = doc.getDocumentElement(); +       +      if (childNode == null) { +        log.info("Failed to parse XMLObject from '" + reference + "'."); +        throw new SLCommandException(4111); +      } +       +      XMLObject xmlObject = createXMLObject(childNode); +       +      setXMLObjectAndReferenceXML(xmlObject, transforms); +       +    } else { +   +      // Include content Base64 encoded. +      XMLObject xmlObject = createXMLObject(streamData.getStream()); +       +      setXMLObjectAndReferenceBase64(xmlObject, transforms); +       +    } +     +  } + +  /** +   * Configures this DataObject as an detached DataObject with the information +   * provided in the given <code>sl:DataObject</code> and optionally +   * <code>transforms</code>. +   *  +   * @param dataObject +   *          the <code>sl:DataObject</code> +   * @param transforms +   *          an optional Transforms object, may be <code>null</code> +   *  +   * @throws SLCommandException +   *           if configuring this DataObject with the information provided in +   *           the <code>sl:DataObject</code> fails. +   * @throws SLRequestException +   *           if the information provided in the <code>sl:DataObject</code> +   *           does not conform to the security layer specification. +   * @throws NullPointerException +   *           if <code>dataObject</code> is <code>null</code> +   */ +  private void setDetachedDataObject( +      Base64XMLLocRefOptRefContentType dataObject, XSECTTransforms transforms) +      throws SLCommandException, SLRequestException { +     +    String referenceURI = dataObject.getReference(); +     +    if (referenceURI == null) { +       +      // not allowed +      log.info("XML structure of the command request contains an " + +          "invalid combination of optional elements or attributes. " + +      "DataObject of structure='detached' must contain a reference."); +      throw new SLRequestException(3003); + +    } else { +       +      DigestMethod dm; +      try { +        dm = ctx.getAlgorithmMethodFactory().createDigestMethod(ctx); +      } catch (NoSuchAlgorithmException e) { +        log.error("Failed to get DigestMethod.", e); +        throw new SLCommandException(4006); +      } catch (InvalidAlgorithmParameterException e) { +        log.error("Failed to get DigestMethod.", e); +        throw new SLCommandException(4006); +      } +       +      String idValue = ctx.getIdValueFactory().createIdValue("Reference"); +       +      reference = new XSECTReference(referenceURI, dm, transforms, null, idValue); +       +      // case D: +      // +      // The Reference attribute contains a URI that is used by the Citizen Card +      // Environment to code the reference to the data object as part of the XML +      // signature (attribute URI in the dsig:Reference) element. The content of +      // sl:DataObject represents the data object. +       +      if (dataObject.getLocRefContent() != null) { +        String locRef = dataObject.getLocRefContent(); +        try { +          this.reference.setDereferencer(new LocRefDereferencer(ctx.getDereferencerContext(), locRef)); +        } catch (URISyntaxException e) { +          log.info("Invalid URI '" + locRef + "' in DataObject.", e); +          throw new SLCommandException(4003); +        } catch (IllegalArgumentException e) { +          log.info("LocRef URI of '" + locRef + "' not supported in DataObject. ", e); +          throw new SLCommandException(4003); +        } +      } else if (dataObject.getBase64Content() != null) { +        byte[] base64Content = dataObject.getBase64Content(); +        this.reference.setDereferencer(new ByteArrayDereferencer(base64Content)); +      } else if (dataObject.getXMLContent() != null) { +        XMLContentType xmlContent = (XMLContentType) dataObject.getXMLContent(); +        byte[] bytes = xmlContent.getRedirectedStream().toByteArray(); +        this.reference.setDereferencer(new ByteArrayDereferencer(bytes)); +      } else { +         +        // case C: +        // +        // The Reference attribute contains a URI that must be resolved by the +        // Citizen Card Environment to obtain the data object. The Reference +        // attribute contains a URI that is used by the Citizen Card Environment +        // to code the reference to the data object as part of the XML signature +        // (attribute URI in the dsig:Reference) element. The content of +        // sl:DataObject remains empty. + +      } +       +    }      +  } + +  /** +   * Returns the preferred <code>sl:TransformInfo</code> from the given list of +   * <code>transformInfos</code>, or <code>null</code> if none of the given +   * <code>transformInfos</code> is preferred over the others. +   *  +   * @param transformsInfos +   *          a list of <code>sl:TransformInfo</code>s +   *  +   * @return the selected <code>sl:TransformInfo</code> or <code>null</code>, if +   *         none is preferred over the others +   */ +  private TransformsInfoType selectPreferredTransformsInfo(List<TransformsInfoType> transformsInfos) { +     +    Map<String, TransformsInfoType> mimeTypes = new HashMap<String, TransformsInfoType>(); +     +    StringBuilder debugString = null; +    if (log.isDebugEnabled()) { +      debugString = new StringBuilder(); +      debugString.append("Got " + transformsInfos.size() + " TransformsInfo(s):"); +    } +     +    for (TransformsInfoType transformsInfoType : transformsInfos) { +      MetaInfoType finalDataMetaInfo = transformsInfoType.getFinalDataMetaInfo(); +      String mimeType = finalDataMetaInfo.getMimeType(); +      String description = finalDataMetaInfo.getDescription(); +      mimeTypes.put(mimeType, transformsInfoType); +      if (debugString != null) { +        debugString.append("\n FinalDataMetaInfo: MIME-Type="); +        debugString.append(mimeType); +        if (description != null) { +          debugString.append(" "); +          debugString.append(description); +        } +      } +    } + +    if (debugString != null) { +      log.debug(debugString); +    } + +    // look for preferred transform +    for (String mimeType : DEFAULT_PREFFERED_MIME_TYPES) { +      if (mimeTypes.containsKey(mimeType)) { +        return mimeTypes.get(mimeType); +      } +    } +     +    // no preferred transform +    return null; +     +  } + +  /** +   * Create an instance of <code>ds:Transforms</code> from the given +   * <code>sl:TransformsInfo</code>. +   *  +   * @param transformsInfo +   *          the <code>sl:TransformsInfo</code> +   *  +   * @return a corresponding unmarshalled <code>ds:Transforms</code>, or +   *         <code>null</code> if the given <code>sl:TransformsInfo</code> does +   *         not contain a <code>dsig:Transforms</code> element +   *  +   * @throws SLRequestException +   *           if the <code>ds:Transforms</code> in the given +   *           <code>transformsInfo</code> are not valid or cannot be parsed. +   *  +   * @throws MarshalException +   *           if the <code>ds:Transforms</code> in the given +   *           <code>transformsInfo</code> cannot be unmarshalled. +   */ +  private XSECTTransforms createTransforms(TransformsInfoType transformsInfo) throws SLRequestException, MarshalException { + +    byte[] transforms = getTransformsBytes((at.gv.egiz.slbinding.impl.TransformsInfoType) transformsInfo); + +    if (transforms != null && transforms.length > 0) { +      // debug +      if (log.isTraceEnabled()) { +        StringBuilder sb = new StringBuilder(); +        sb.append("Trying to parse transforms:\n"); +        sb.append(new String(transforms, Charset.forName("UTF-8"))); +        log.trace(sb); +      } + +      DOMImplementationLS domImplLS = DOMUtils.getDOMImplementationLS(); +      LSInput input = domImplLS.createLSInput(); +      input.setByteStream(new ByteArrayInputStream(transforms)); + +      LSParser parser = domImplLS.createLSParser( +          DOMImplementationLS.MODE_SYNCHRONOUS, null); +      DOMConfiguration domConfig = parser.getDomConfig(); +      SimpleDOMErrorHandler errorHandler = new SimpleDOMErrorHandler(); +      domConfig.setParameter("error-handler", errorHandler); +      domConfig.setParameter("validate", Boolean.FALSE); + +      Document document; +      try { +        document = parser.parse(input); +      } catch (DOMException e) { +        log.info("Failed to parse dsig:Transforms.", e); +        throw new SLRequestException(3002); +      } catch (LSException e) { +        log.info("Failed to parse dsig:Transforms.", e); +        throw new SLRequestException(3002); +      } + +      // adopt ds:Transforms +      Element transformsElt = document.getDocumentElement(); +      Node adoptedTransforms = ctx.getDocument().adoptNode(transformsElt); + +      DOMCryptoContext context = new DOMCryptoContext(); + +      // unmarshall ds:Transforms +      return new XSECTTransforms(context, adoptedTransforms); + +    } else { +      return null; +    } + + +//    TransformsType transformsType = transformsInfo.getTransforms(); +//    if (transformsType == null) { +//      return null; +//    } +//    List<TransformType> transformList = transformsType.getTransform(); +// +//    DOMImplementationLS domImplLS = DOMUtils.getDOMImplementationLS(); +////    Document transformsDoc = ((DOMImplementation) domImplLS).createDocument("http://www.w3.org/2000/09/xmldsig#", "Transforms", null); +////    Element transforms = transformsDoc.getDocumentElement(); +//    Document transformsDoc = DOMUtils.createDocument(); +//    Element transforms = transformsDoc.createElementNS( +//            "http://www.w3.org/2000/09/xmldsig#", +//            Signature.XMLDSIG_PREFIX + ":Transforms"); +//    transformsDoc.appendChild(transforms); +// +//    for (TransformType transformType : transformList) { +//      log.trace("found " + transformType.getClass().getName()); +//      Element transform = transformsDoc.createElementNS( +//              "http://www.w3.org/2000/09/xmldsig#", +//              Signature.XMLDSIG_PREFIX + ":Transform"); +//      String algorithm = transformType.getAlgorithm(); +//      if (algorithm != null) { +//        log.trace("found algorithm " + algorithm); +//        transform.setAttribute("Algorithm", algorithm); +//      } +// +//      at.gv.egiz.slbinding.impl.TransformType t = (at.gv.egiz.slbinding.impl.TransformType) transformType; +//      byte[] redirectedBytes = t.getRedirectedStream().toByteArray(); +//      if (redirectedBytes != null && redirectedBytes.length > 0) { +//        if (log.isTraceEnabled()) { +//          StringBuilder sb = new StringBuilder(); +//          sb.append("Trying to parse dsig:Transform:\n"); +//          sb.append(new String(redirectedBytes, Charset.forName("UTF-8"))); +//          log.trace(sb); +//        } +//        LSInput input = domImplLS.createLSInput(); +//        input.setByteStream(new ByteArrayInputStream(redirectedBytes)); +// +//        LSParser parser = domImplLS.createLSParser( +//            DOMImplementationLS.MODE_SYNCHRONOUS, null); +//        DOMConfiguration domConfig = parser.getDomConfig(); +//        SimpleDOMErrorHandler errorHandler = new SimpleDOMErrorHandler(); +//        domConfig.setParameter("error-handler", errorHandler); +//        domConfig.setParameter("validate", Boolean.FALSE); +// +//        try { +//          Document redirectedDoc = parser.parse(input); +//          Node redirected = transformsDoc.adoptNode(redirectedDoc.getDocumentElement()); +//          transform.appendChild(redirected); +// +//          //not supported by Xerces2.9.1 +////          Node redirected = parser.parseWithContext(input, transform, LSParser.ACTION_APPEND_AS_CHILDREN); +// +//        } catch (DOMException e) { +//          log.info("Failed to parse dsig:Transform.", e); +//          throw new SLRequestException(3002); +//        } catch (LSException e) { +//          log.info("Failed to parse dsig:Transform.", e); +//          throw new SLRequestException(3002); +//        } +//      } +//      transforms.appendChild(transform); +//    } +// +//    //adopt ds:Transforms +//    Node adoptedTransforms = ctx.getDocument().adoptNode(transforms); +//    DOMCryptoContext context = new DOMCryptoContext(); +// +//    // unmarshall ds:Transforms +//    return new XSECTTransforms(context, adoptedTransforms); + +  } +   +  /** +   * Sets the <code>mimeType</code> and the <code>description</code> value +   * for this DataObject. +   *  +   * @param metaInfoType the <code>sl:FinalMetaDataInfo</code> +   *  +   * @throws NullPointerException if <code>metaInfoType</code> is <code>null</code> +   */ +  private void setFinalDataMetaInfo(MetaInfoType metaInfoType) { +     +    this.mimeType = metaInfoType.getMimeType(); +    this.description = metaInfoType.getDescription(); +     +  } +   +  /** +   * Selects an appropriate transformation path (if present) from the given list +   * of <code>sl:TransformInfos</code>, sets the corresponding final data meta info and +   * returns the corresponding unmarshalled <code>ds:Transforms</code>. +   *  +   * @param transformsInfos the <code>sl:TransformInfos</code> +   *  +   * @return the unmarshalled <code>ds:Transforms</code>, or <code>null</code> if +   * no transformation path has been selected. +   *  +   * @throws SLRequestException if the given list <code>ds:TransformsInfo</code> contains +   * an invalid <code>ds:Transforms</code> element, or no suitable transformation path +   * can be found.  +   */ +  private XSECTTransforms createTransformsAndSetFinalDataMetaInfo( +      List<TransformsInfoType> transformsInfos) throws SLRequestException { + +    TransformsInfoType preferredTransformsInfo = selectPreferredTransformsInfo(transformsInfos); +    // try preferred transform +    if (preferredTransformsInfo != null) { + +      try { +        XSECTTransforms transforms = createTransforms(preferredTransformsInfo); +        setFinalDataMetaInfo(preferredTransformsInfo.getFinalDataMetaInfo()); +        return transforms; +      } catch (MarshalException e) { +       +        String mimeType = preferredTransformsInfo.getFinalDataMetaInfo().getMimeType(); +        log.info("Failed to unmarshal preferred transformation path (MIME-Type=" +            + mimeType + ").", e); +       +      } + +    } + +    // look for another suitable transformation path +    for (TransformsInfoType transformsInfoType : transformsInfos) { +       +      try { +        XSECTTransforms transforms = createTransforms(transformsInfoType); +        setFinalDataMetaInfo(transformsInfoType.getFinalDataMetaInfo()); +        return transforms; +      } catch (MarshalException e) { + +        String mimeType = transformsInfoType.getFinalDataMetaInfo().getMimeType(); +        log.info("Failed to unmarshal transformation path (MIME-Type=" +            + mimeType + ").", e); +      } +       +    } + +    // no suitable transformation path found +    throw new SLRequestException(3003); +     +  } + +  /** +   * Create an XMLObject with the Base64 encoding of the given +   * <code>content</code>. +   *  +   * @param content +   *          the to-be Base64 encoded content +   * @return an XMLObject with the Base64 encoded <code>content</code> +   */ +  private XMLObject createXMLObject(InputStream content) { +     +    Text textNode; +    try { +      textNode = at.gv.egiz.dom.DOMUtils.createBase64Text(content, ctx.getDocument()); +    } catch (IOException e) { +      log.error(e); +      throw new SLRuntimeException(e); +    } + +    DOMStructure structure = new DOMStructure(textNode); +     +    String idValue = ctx.getIdValueFactory().createIdValue("Object"); + +    return ctx.getSignatureFactory().newXMLObject(Collections.singletonList(structure), idValue, null, null); +     +  } +   +  /** +   * Create an XMLObject with the given <code>content</code> node. +   *  +   * @param content the content node +   *  +   * @return an XMLObject with the given <code>content</code> +   */ +  private XMLObject createXMLObject(Node content) { +     +    String idValue = ctx.getIdValueFactory().createIdValue("Object"); +     +    List<DOMStructure> structures = Collections.singletonList(new DOMStructure(content)); +     +    return ctx.getSignatureFactory().newXMLObject(structures, idValue, null, null); +     +  } + +  /** +   * Sets the given <code>xmlObject</code> and creates and sets a corresponding +   * <code>Reference</code>. +   * <p> +   * A transform to Base64-decode the xmlObject's content is inserted at the top +   * of to the optional <code>transforms</code> if given, or to a newly created +   * <code>Transforms</code> element if <code>transforms</code> is +   * <code>null</code>. +   *  +   * @param xmlObject +   *          the XMLObject +   * @param transforms +   *          an optional <code>Transforms</code> element (may be +   *          <code>null</code>) +   *  +   * @throws SLCommandException +   *           if creating the Reference fails +   * @throws NullPointerException +   *           if <code>xmlObject</code> is <code>null</code> +   */ +  private void setXMLObjectAndReferenceBase64(XMLObject xmlObject, XSECTTransforms transforms) throws SLCommandException { +     +    // create reference URI +    // +    // NOTE: the ds:Object can be referenced directly, as the Base64 transform +    // operates on the text() of the input nodelist. +    // +    String referenceURI = "#" + xmlObject.getId(); +   +    // create Base64 Transform +    Transform transform; +    try { +      transform = ctx.getSignatureFactory().newTransform(Transform.BASE64, (TransformParameterSpec) null); +    } catch (NoSuchAlgorithmException e) { +      // algorithm must be present +      throw new SLRuntimeException(e); +    } catch (InvalidAlgorithmParameterException e) { +      // algorithm does not take parameters +      throw new SLRuntimeException(e); +    } +     +    if (transforms == null) { +      transforms = new XSECTTransforms(Collections.singletonList(transform));  +    } else { +      transforms.insertTransform(transform); +    } +   +    DigestMethod dm; +    try { +      dm = ctx.getAlgorithmMethodFactory().createDigestMethod(ctx); +    } catch (NoSuchAlgorithmException e) { +      log.error("Failed to get DigestMethod.", e); +      throw new SLCommandException(4006); +    } catch (InvalidAlgorithmParameterException e) { +      log.error("Failed to get DigestMethod.", e); +      throw new SLCommandException(4006); +    } +    String id = ctx.getIdValueFactory().createIdValue("Reference"); +     +    this.xmlObject = xmlObject; +    this.reference = new XSECTReference(referenceURI, dm, transforms, null, id); +     +  } + +  /** +   * Sets the given <code>xmlObject</code> and creates and sets a corresponding +   * <code>Reference</code>. +   * <p> +   * A transform to select the xmlObject's content is inserted at the top of to +   * the optional <code>transforms</code> if given, or to a newly created +   * <code>Transforms</code> element if <code>transforms</code> is +   * <code>null</code>. +   * </p> +   *  +   * @param xmlObject +   *          the XMLObject +   * @param transforms +   *          an optional <code>Transforms</code> element (may be +   *          <code>null</code>) +   *  +   * @throws SLCommandException +   *           if creating the Reference fails +   * @throws NullPointerException +   *           if <code>xmlObject</code> is <code>null</code> +   */ +  private void setXMLObjectAndReferenceXML(XMLObject xmlObject, XSECTTransforms transforms) throws SLCommandException { +     +    // create reference URI +    String referenceURI = "#" + xmlObject.getId(); +     +    // create Transform to select ds:Object's children +    Transform xpathTransform; +    Transform c14nTransform; +    try { + +      XPathType xpath = new XPathType("id(\"" + xmlObject.getId() + "\")/node()", XPathType.Filter.INTERSECT); +      List<XPathType> xpaths = Collections.singletonList(xpath); +      XPathFilter2ParameterSpec params = new XPathFilter2ParameterSpec(xpaths); + +      xpathTransform = ctx.getSignatureFactory().newTransform(Transform.XPATH2, params); + +      // add exclusive canonicalization to avoid signing the namespace context of the ds:Object +      c14nTransform = ctx.getSignatureFactory().newTransform(CanonicalizationMethod.EXCLUSIVE, (TransformParameterSpec) null); +       +    } catch (NoSuchAlgorithmException e) { +      // algorithm must be present +      throw new SLRuntimeException(e); +    } catch (InvalidAlgorithmParameterException e) { +      // params must be appropriate +      throw new SLRuntimeException(e); +    } +   +    if (transforms == null) { +      List<Transform> newTransfroms = new ArrayList<Transform>(); +      newTransfroms.add(xpathTransform); +      newTransfroms.add(c14nTransform); +      transforms = new XSECTTransforms(newTransfroms); +    } else { +      transforms.insertTransform(xpathTransform); +    } +     +    DigestMethod dm; +    try { +      dm = ctx.getAlgorithmMethodFactory().createDigestMethod(ctx); +    } catch (NoSuchAlgorithmException e) { +      log.error("Failed to get DigestMethod.", e); +      throw new SLCommandException(4006); +    } catch (InvalidAlgorithmParameterException e) { +      log.error("Failed to get DigestMethod.", e); +      throw new SLCommandException(4006); +    } +    String id = ctx.getIdValueFactory().createIdValue("Reference"); + +    this.xmlObject = xmlObject; +    this.reference = new XSECTReference(referenceURI, dm, transforms, null, id); +     +  } + +  /** +   * Parses the given <code>xmlContent</code> and returns a corresponding +   * document fragment. +   *  +   * <p> +   * The to-be parsed content is surrounded by <dummy> ... </dummy> elements to +   * allow for mixed (e.g. Text and Element) content in XMLContent. +   * </p> +   *  +   * @param xmlContent +   *          the XMLContent to-be parsed +   *  +   * @return a document fragment containing the parsed nodes +   *  +   * @throws SLCommandException +   *           if parsing the given <code>xmlContent</code> fails +   *  +   * @throws NullPointerException +   *           if <code>xmlContent</code> is <code>null</code> +   */ +  private DocumentFragment parseDataObject(XMLContentType xmlContent) throws SLCommandException { +     +    ByteArrayOutputStream redirectedStream =  xmlContent.getRedirectedStream(); +   +    // Note: We can assume a fixed character encoding of UTF-8 for the +    // content of the redirect stream as the content has already been parsed +    // and serialized again to the redirect stream. +     +    List<InputStream> inputStreams = new ArrayList<InputStream>(); +    try { +      // dummy start element +      inputStreams.add(new ByteArrayInputStream("<dummy>".getBytes("UTF-8"))); +   +      // content +      inputStreams.add(new ByteArrayInputStream(redirectedStream.toByteArray())); +       +      // dummy end element +      inputStreams.add(new ByteArrayInputStream("</dummy>".getBytes("UTF-8"))); +    } catch (UnsupportedEncodingException e) { +      throw new SLRuntimeException(e); +    } +     +    SequenceInputStream inputStream = new SequenceInputStream(Collections.enumeration(inputStreams)); +   +    // parse DataObject +    Document doc = parseDataObject(inputStream, "UTF-8"); +     +    Element documentElement = doc.getDocumentElement(); +   +    if (documentElement == null || +        !"dummy".equals(documentElement.getLocalName())) { +      log.info("Failed to parse DataObject XMLContent."); +      throw new SLCommandException(4111); +    } +     +    DocumentFragment fragment = doc.createDocumentFragment(); +    while (documentElement.getFirstChild() != null) { +      fragment.appendChild(documentElement.getFirstChild()); +    } +     +    // log parsed document +    if (log.isTraceEnabled()) { +       +      StringWriter writer = new StringWriter(); +       +      writer.write("DataObject:\n"); +       +      LSOutput output = domImplLS.createLSOutput(); +      output.setCharacterStream(writer); +      output.setEncoding("UTF-8"); +      LSSerializer serializer = domImplLS.createLSSerializer(); +      serializer.getDomConfig().setParameter("xml-declaration", Boolean.FALSE); +      serializer.write(fragment, output); +       +      log.trace(writer.toString()); +    } +     +    return fragment; +     +  } + +  /** +   * Parses the given <code>inputStream</code> using the given +   * <code>encoding</code> and returns the parsed document. +   *  +   * @param inputStream +   *          the to-be parsed input +   *  +   * @param encoding +   *          the encoding to be used for parsing the given +   *          <code>inputStream</code> +   *  +   * @return the parsed document +   *  +   * @throws SLCommandException +   *           if parsing the <code>inputStream</code> fails. +   *  +   * @throws NullPointerException +   *           if <code>inputStram</code> is <code>null</code> +   */ +  private Document parseDataObject(InputStream inputStream, String encoding) throws SLCommandException { + +    LSInput input = domImplLS.createLSInput(); +    input.setByteStream(inputStream); + +    if (encoding != null) { +      input.setEncoding(encoding); +    } +     +    LSParser parser = domImplLS.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null); +    DOMConfiguration domConfig = parser.getDomConfig(); +    SimpleDOMErrorHandler errorHandler = new SimpleDOMErrorHandler(); +    domConfig.setParameter("error-handler", errorHandler); +    domConfig.setParameter("validate", Boolean.FALSE); + +    Document doc; +    try { +      doc = parser.parse(input); +    } catch (DOMException e) { +      log.info("Existing XML document cannot be parsed.", e); +      throw new SLCommandException(4111); +    } catch (LSException e) { +      log.info("Existing XML document cannot be parsed. ", e); +      throw new SLCommandException(4111); +    } +     +    if (errorHandler.hasErrors()) { +      // log errors +      if (log.isInfoEnabled()) { +        List<String> errorMessages = errorHandler.getErrorMessages(); +        StringBuffer sb = new StringBuffer(); +        for (String errorMessage : errorMessages) { +          sb.append(" "); +          sb.append(errorMessage); +        } +        log.info("Existing XML document cannot be parsed. " + sb.toString()); +      } +      throw new SLCommandException(4111); +    } + +    return doc; +     +  } + + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java index 8baa0137..9182e824 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java @@ -87,6 +87,8 @@ import at.gv.egiz.bku.utils.urldereferencer.StreamData;  import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer;  import at.gv.egiz.bku.utils.urldereferencer.URLDereferencerContext;  import at.gv.egiz.dom.DOMUtils; +import at.gv.egiz.marshal.NamespacePrefix; +import at.gv.egiz.marshal.NamespacePrefixMapperImpl;  import at.gv.egiz.slbinding.impl.XMLContentType;  import at.gv.egiz.stal.STAL;  import at.gv.egiz.xades.QualifyingPropertiesException; @@ -99,6 +101,7 @@ import at.gv.egiz.xades.QualifyingPropertiesFactory;   * @author mcentner   */  public class Signature { +  public static final String XMLDSIG_PREFIX = "dsig";    /**     * Logging facility. @@ -407,7 +410,7 @@ public class Signature {      signContext.setProperty("javax.xml.crypto.dsig.cacheReference", Boolean.TRUE); -    signContext.putNamespacePrefix(XMLSignature.XMLNS, "dsig"); +    signContext.putNamespacePrefix(XMLSignature.XMLNS,XMLDSIG_PREFIX);       signContext.setURIDereferencer(new URIDereferncerAdapter(ctx.getDereferencerContext())); diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/xsect/SignatureTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/xsect/SignatureTest.java index 78172dcb..7ce7b42d 100644 --- a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/xsect/SignatureTest.java +++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/xsect/SignatureTest.java @@ -14,185 +14,186 @@  * See the License for the specific language governing permissions and  * limitations under the License.  */ -package at.gv.egiz.bku.slcommands.impl.xsect;
 -
 -import static org.junit.Assert.assertNotNull;
 -import static org.junit.Assert.assertNull;
 -import static org.junit.Assert.assertTrue;
 -
 -import iaik.xml.crypto.XSecProvider;
 -
 -import java.io.IOException;
 -import java.io.InputStream;
 -import java.security.KeyStore;
 -import java.security.KeyStoreException;
 -import java.security.NoSuchAlgorithmException;
 -import java.security.PrivateKey;
 -import java.security.UnrecoverableKeyException;
 -import java.security.cert.CertificateException;
 -import java.security.cert.X509Certificate;
 -import java.util.List;
 -
 +package at.gv.egiz.bku.slcommands.impl.xsect; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import iaik.xml.crypto.XSecProvider; + +import java.io.IOException; +import java.io.InputStream; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.UnrecoverableKeyException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.List; +  import javax.net.ssl.HostnameVerifier;  import javax.net.ssl.SSLSocketFactory; -import javax.xml.bind.JAXBContext;
 -import javax.xml.bind.JAXBElement;
 -import javax.xml.bind.JAXBException;
 -import javax.xml.bind.Unmarshaller;
 -import javax.xml.crypto.MarshalException;
 -import javax.xml.crypto.dsig.CanonicalizationMethod;
 -import javax.xml.crypto.dsig.DigestMethod;
 -import javax.xml.crypto.dsig.Reference;
 -import javax.xml.crypto.dsig.SignatureMethod;
 -import javax.xml.crypto.dsig.Transform;
 -import javax.xml.crypto.dsig.XMLObject;
 -import javax.xml.crypto.dsig.XMLSignatureException;
 -import javax.xml.crypto.dsig.XMLSignatureFactory;
 -import javax.xml.crypto.dsig.dom.DOMSignContext;
 -import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
 -import javax.xml.crypto.dsig.spec.DigestMethodParameterSpec;
 -import javax.xml.crypto.dsig.spec.SignatureMethodParameterSpec;
 -import javax.xml.stream.XMLEventReader;
 -import javax.xml.stream.XMLInputFactory;
 -import javax.xml.stream.XMLStreamException;
 -
 -import org.junit.BeforeClass;
 -import org.junit.Test;
 -import org.w3c.dom.Document;
 -import org.w3c.dom.Node;
 -import org.w3c.dom.ls.DOMImplementationLS;
 -import org.w3c.dom.ls.LSOutput;
 -import org.w3c.dom.ls.LSSerializer;
 -
 -import at.buergerkarte.namespaces.securitylayer._1.CreateXMLSignatureRequestType;
 -import at.buergerkarte.namespaces.securitylayer._1.DataObjectInfoType;
 -import at.buergerkarte.namespaces.securitylayer._1.ObjectFactory;
 -import at.buergerkarte.namespaces.securitylayer._1.SignatureInfoCreationType;
 -import at.gv.egiz.bku.slexceptions.SLCommandException;
 -import at.gv.egiz.bku.slexceptions.SLRequestException;
 +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.crypto.MarshalException; +import javax.xml.crypto.dsig.CanonicalizationMethod; +import javax.xml.crypto.dsig.DigestMethod; +import javax.xml.crypto.dsig.Reference; +import javax.xml.crypto.dsig.SignatureMethod; +import javax.xml.crypto.dsig.Transform; +import javax.xml.crypto.dsig.XMLObject; +import javax.xml.crypto.dsig.XMLSignatureException; +import javax.xml.crypto.dsig.XMLSignatureFactory; +import javax.xml.crypto.dsig.dom.DOMSignContext; +import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec; +import javax.xml.crypto.dsig.spec.DigestMethodParameterSpec; +import javax.xml.crypto.dsig.spec.SignatureMethodParameterSpec; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.ls.DOMImplementationLS; +import org.w3c.dom.ls.LSOutput; +import org.w3c.dom.ls.LSSerializer; + +import at.buergerkarte.namespaces.securitylayer._1.CreateXMLSignatureRequestType; +import at.buergerkarte.namespaces.securitylayer._1.DataObjectInfoType; +import at.buergerkarte.namespaces.securitylayer._1.ObjectFactory; +import at.buergerkarte.namespaces.securitylayer._1.SignatureInfoCreationType; +import at.gv.egiz.bku.slexceptions.SLCommandException; +import at.gv.egiz.bku.slexceptions.SLRequestException;  import at.gv.egiz.bku.slexceptions.SLViewerException; -import at.gv.egiz.bku.utils.urldereferencer.StreamData;
 -import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer;
 -import at.gv.egiz.bku.utils.urldereferencer.URLDereferencerContext;
 -import at.gv.egiz.bku.utils.urldereferencer.URLProtocolHandler;
 -import at.gv.egiz.dom.DOMUtils;
 -import at.gv.egiz.slbinding.RedirectEventFilter;
 -import at.gv.egiz.slbinding.RedirectUnmarshallerListener;
 -
 -public class SignatureTest {
 -
 -  private class AlgorithmMethodFactoryImpl implements AlgorithmMethodFactory {
 -  
 -    @Override
 -    public CanonicalizationMethod createCanonicalizationMethod(
 -        SignatureContext signatureContext) {
 -      
 -      XMLSignatureFactory signatureFactory = signatureContext.getSignatureFactory();
 -      
 -      try {
 -        return signatureFactory.newCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE, (C14NMethodParameterSpec) null);
 -      } catch (Exception e) {
 -        throw new RuntimeException(e);
 -      } 
 -    }
 -  
 -    @Override
 -    public DigestMethod createDigestMethod(SignatureContext signatureContext) {
 -  
 -      XMLSignatureFactory signatureFactory = signatureContext.getSignatureFactory();
 -  
 -      try {
 -        return signatureFactory.newDigestMethod(DigestMethod.SHA1, (DigestMethodParameterSpec) null);
 -      } catch (Exception e) {
 -        throw new RuntimeException(e);
 -      } 
 -    }
 -  
 -    @Override
 -    public SignatureMethod createSignatureMethod(
 -        SignatureContext signatureContext) {
 -  
 -      XMLSignatureFactory signatureFactory = signatureContext.getSignatureFactory();
 -  
 -      try {
 -        return signatureFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, (SignatureMethodParameterSpec) null);
 -      } catch (Exception e) {
 -        throw new RuntimeException(e);
 -      } 
 -  
 -    }
 -    
 -  }
 -
 -  private static final String RESOURCE_PREFIX = "at/gv/egiz/bku/slcommands/impl/";
 -  
 -  private static Unmarshaller unmarshaller;
 -  
 -  private static PrivateKey privateKey;
 -
 -  private static X509Certificate certificate;
 -  
 -  @BeforeClass
 -  public static void setUpClass() throws JAXBException, NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException, UnrecoverableKeyException {
 -    
 -    XSecProvider.addAsProvider(true);
 -    
 -    String packageName = ObjectFactory.class.getPackage().getName();
 -    packageName += ":"
 -        + org.w3._2000._09.xmldsig_.ObjectFactory.class.getPackage().getName();
 -    JAXBContext jaxbContext = JAXBContext.newInstance(packageName);
 -
 -    unmarshaller = jaxbContext.createUnmarshaller();
 -    
 -    initURLDereferencer();
 -    
 -    ClassLoader classLoader = SignatureTest.class.getClassLoader();
 -    InputStream certStream = classLoader.getResourceAsStream(RESOURCE_PREFIX + "Cert.p12");
 -    assertNotNull("Certificate not found.", certStream);
 -        
 -    char[] passwd = "1622".toCharArray();
 -    
 -    KeyStore keystore = KeyStore.getInstance("PKCS12");
 -    keystore.load(certStream, passwd);
 -    String firstAlias = keystore.aliases().nextElement();
 -    certificate = (X509Certificate) keystore.getCertificate(firstAlias);
 -    privateKey = (PrivateKey) keystore.getKey(firstAlias, passwd);
 -    
 -  }
 -
 -  private static void initURLDereferencer() {
 -    
 -    URLDereferencer.getInstance().registerHandler("testlocal", new URLProtocolHandler() {
 -      
 -      @Override
 -      public StreamData dereference(String url, URLDereferencerContext context)
 -          throws IOException {
 -
 -        ClassLoader classLoader = SignatureTest.class.getClassLoader();
 -        
 -        String filename = url.split(":", 2)[1];
 -
 -        InputStream stream = classLoader.getResourceAsStream(RESOURCE_PREFIX + filename);
 -        
 -        if (stream == null) {
 -
 -          throw new IOException("Failed to resolve resource '" + url + "'.");
 -
 -        } else {
 -
 -          String contentType;
 -          if (filename.endsWith(".xml")) {
 -            contentType = "text/xml";
 -          } else if (filename.endsWith(".txt")) {
 -            contentType = "text/plain";
 -          } else {
 -            contentType = "";
 -          }
 -          
 -          return new StreamData(url, contentType, stream);
 -          
 -        }
 -        
 +import at.gv.egiz.bku.utils.urldereferencer.StreamData; +import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer; +import at.gv.egiz.bku.utils.urldereferencer.URLDereferencerContext; +import at.gv.egiz.bku.utils.urldereferencer.URLProtocolHandler; +import at.gv.egiz.dom.DOMUtils; +import at.gv.egiz.slbinding.RedirectEventFilter; +import at.gv.egiz.slbinding.RedirectUnmarshallerListener; +import org.junit.Ignore; + +public class SignatureTest { + +  private class AlgorithmMethodFactoryImpl implements AlgorithmMethodFactory { +   +    @Override +    public CanonicalizationMethod createCanonicalizationMethod( +        SignatureContext signatureContext) { +       +      XMLSignatureFactory signatureFactory = signatureContext.getSignatureFactory(); +       +      try { +        return signatureFactory.newCanonicalizationMethod(CanonicalizationMethod.EXCLUSIVE, (C14NMethodParameterSpec) null); +      } catch (Exception e) { +        throw new RuntimeException(e); +      }  +    } +   +    @Override +    public DigestMethod createDigestMethod(SignatureContext signatureContext) { +   +      XMLSignatureFactory signatureFactory = signatureContext.getSignatureFactory(); +   +      try { +        return signatureFactory.newDigestMethod(DigestMethod.SHA1, (DigestMethodParameterSpec) null); +      } catch (Exception e) { +        throw new RuntimeException(e); +      }  +    } +   +    @Override +    public SignatureMethod createSignatureMethod( +        SignatureContext signatureContext) { +   +      XMLSignatureFactory signatureFactory = signatureContext.getSignatureFactory(); +   +      try { +        return signatureFactory.newSignatureMethod(SignatureMethod.RSA_SHA1, (SignatureMethodParameterSpec) null); +      } catch (Exception e) { +        throw new RuntimeException(e); +      }  +   +    } +     +  } + +  private static final String RESOURCE_PREFIX = "at/gv/egiz/bku/slcommands/impl/"; +   +  private static Unmarshaller unmarshaller; +   +  private static PrivateKey privateKey; + +  private static X509Certificate certificate; +   +  @BeforeClass +  public static void setUpClass() throws JAXBException, NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException, UnrecoverableKeyException { +     +    XSecProvider.addAsProvider(true); +     +    String packageName = ObjectFactory.class.getPackage().getName(); +    packageName += ":" +        + org.w3._2000._09.xmldsig_.ObjectFactory.class.getPackage().getName(); +    JAXBContext jaxbContext = JAXBContext.newInstance(packageName); + +    unmarshaller = jaxbContext.createUnmarshaller(); +     +    initURLDereferencer(); +     +    ClassLoader classLoader = SignatureTest.class.getClassLoader(); +    InputStream certStream = classLoader.getResourceAsStream(RESOURCE_PREFIX + "Cert.p12"); +    assertNotNull("Certificate not found.", certStream); +         +    char[] passwd = "1622".toCharArray(); +     +    KeyStore keystore = KeyStore.getInstance("PKCS12"); +    keystore.load(certStream, passwd); +    String firstAlias = keystore.aliases().nextElement(); +    certificate = (X509Certificate) keystore.getCertificate(firstAlias); +    privateKey = (PrivateKey) keystore.getKey(firstAlias, passwd); +     +  } + +  private static void initURLDereferencer() { +     +    URLDereferencer.getInstance().registerHandler("testlocal", new URLProtocolHandler() { +       +      @Override +      public StreamData dereference(String url, URLDereferencerContext context) +          throws IOException { + +        ClassLoader classLoader = SignatureTest.class.getClassLoader(); +         +        String filename = url.split(":", 2)[1]; + +        InputStream stream = classLoader.getResourceAsStream(RESOURCE_PREFIX + filename); +         +        if (stream == null) { + +          throw new IOException("Failed to resolve resource '" + url + "'."); + +        } else { + +          String contentType; +          if (filename.endsWith(".xml")) { +            contentType = "text/xml"; +          } else if (filename.endsWith(".txt")) { +            contentType = "text/plain"; +          } else { +            contentType = ""; +          } +           +          return new StreamData(url, contentType, stream); +           +        } +                }        @Override @@ -205,558 +206,600 @@ public class SignatureTest {        public void setSSLSocketFactory(SSLSocketFactory socketFactory) {          // TODO Auto-generated method stub -      }
 -      
 -    });
 -    
 -  }
 -  
 -  private Object unmarshal(String file) throws XMLStreamException, JAXBException {
 -
 -    ClassLoader classLoader = SignatureTest.class.getClassLoader();
 -    InputStream resourceStream = classLoader.getResourceAsStream(RESOURCE_PREFIX + file);
 -    assertNotNull(resourceStream);
 -
 -    XMLInputFactory inputFactory = XMLInputFactory.newInstance();
 -    XMLEventReader eventReader = inputFactory.createXMLEventReader(resourceStream);
 -    RedirectEventFilter redirectEventFilter = new RedirectEventFilter();
 -    XMLEventReader filteredReader = inputFactory.createFilteredReader(eventReader, redirectEventFilter);
 -
 -    unmarshaller.setListener(new RedirectUnmarshallerListener(redirectEventFilter));
 -
 -    return unmarshaller.unmarshal(filteredReader);
 -    
 -  }
 -  
 -  //
 -  //
 -  // SignatureInfo
 -  //
 -  //
 -  
 -  @SuppressWarnings("unchecked")
 -  private SignatureInfoCreationType unmarshalSignatureInfo(String file) throws JAXBException, XMLStreamException {
 -
 -    Object object = unmarshal(file);
 -
 -    Object requestType = ((JAXBElement) object).getValue();
 -    
 -    assertTrue(requestType instanceof CreateXMLSignatureRequestType);
 -    
 -    SignatureInfoCreationType signatureInfo = ((CreateXMLSignatureRequestType) requestType).getSignatureInfo(); 
 -    
 -    assertNotNull(signatureInfo);
 -    
 -    return signatureInfo;
 -    
 -  }
 -
 -  @Test
 -  public void testSetSignatureInfo_Base64_1() throws JAXBException, SLCommandException, XMLStreamException {
 -
 -    SignatureInfoCreationType signatureInfo = unmarshalSignatureInfo("SignatureInfo_Base64_1.xml");
 -    
 -    Signature signature = new Signature(null, new IdValueFactoryImpl(), null);
 -    
 -    signature.setSignatureInfo(signatureInfo);
 -    
 -    Node parent = signature.getParent();
 -    Node nextSibling = signature.getNextSibling();
 -
 -    assertNotNull(parent);
 -    assertTrue("urn:document".equals(parent.getNamespaceURI()));
 -    assertTrue("XMLDocument".equals(parent.getLocalName()));
 -    
 -    assertNotNull(nextSibling);
 -    assertTrue("urn:document".equals(nextSibling.getNamespaceURI()));
 -    assertTrue("Paragraph".equals(nextSibling.getLocalName()));
 -    
 -  }
 -
 -  @Test
 -  public void testSetSignature_Base64_2() throws JAXBException, SLCommandException, XMLStreamException {
 -
 -    SignatureInfoCreationType signatureInfo = unmarshalSignatureInfo("SignatureInfo_Base64_2.xml");
 -    
 -    Signature signature = new Signature(null, new IdValueFactoryImpl(), null);
 -    
 -    signature.setSignatureInfo(signatureInfo);
 -    
 -    Node parent = signature.getParent();
 -    Node nextSibling = signature.getNextSibling();
 -
 -    assertNotNull(parent);
 -    assertTrue("XMLDocument".equals(parent.getLocalName()));
 -    
 -    assertNotNull(nextSibling);
 -    assertTrue("Paragraph".equals(nextSibling.getLocalName()));
 -    
 -  }
 -
 -  @Test
 -  public void testSetSignature_Base64_3() throws JAXBException, SLCommandException, XMLStreamException {
 -
 -    SignatureInfoCreationType signatureInfo = unmarshalSignatureInfo("SignatureInfo_Base64_3.xml");
 -    
 -    Signature signature = new Signature(null, new IdValueFactoryImpl(), null);
 -    
 -    signature.setSignatureInfo(signatureInfo);
 -    
 -    Node parent = signature.getParent();
 -    Node nextSibling = signature.getNextSibling();
 -
 -    assertNotNull(parent);
 -    assertTrue("XMLDocument".equals(parent.getLocalName()));
 -    
 -    assertNotNull(nextSibling);
 -    assertTrue("Paragraph".equals(nextSibling.getLocalName()));
 -    
 -  }
 -
 -  @Test
 -  public void testSetSignatureInfo_XMLContent_1() throws JAXBException, SLCommandException, XMLStreamException {
 -
 -    SignatureInfoCreationType signatureInfo = unmarshalSignatureInfo("SignatureInfo_XMLContent_1.xml");
 -    
 -    Signature signature = new Signature(null, new IdValueFactoryImpl(), null);
 -    
 -    signature.setSignatureInfo(signatureInfo);
 -    
 -    Node parent = signature.getParent();
 -    Node nextSibling = signature.getNextSibling();
 -    
 -    assertNotNull(parent);
 -    assertTrue("urn:document".equals(parent.getNamespaceURI()));
 -    assertTrue("Whole".equals(parent.getLocalName()));
 -    
 -    assertNull(nextSibling);
 -    
 -  }
 -
 -  @Test
 -  public void testSetSignature_Reference_1() throws JAXBException, SLCommandException, XMLStreamException {
 -
 -    SignatureInfoCreationType signatureInfo = unmarshalSignatureInfo("SignatureInfo_Reference_1.xml");
 -    
 -    Signature signature = new Signature(null, new IdValueFactoryImpl(), null);
 -    
 -    signature.setSignatureInfo(signatureInfo);
 -    
 -    Node parent = signature.getParent();
 -    Node nextSibling = signature.getNextSibling();
 -    
 -    assertNotNull(parent);
 -    assertTrue("urn:document".equals(parent.getNamespaceURI()));
 -    assertTrue("Paragraph".equals(parent.getLocalName()));
 -    
 -    assertNull(nextSibling);
 -    
 -  }
 -
 -  //
 -  //
 -  // DataObject
 -  //
 -  //
 -
 -  @SuppressWarnings("unchecked")
 -  private List<DataObjectInfoType> unmarshalDataObjectInfo(String file) throws JAXBException, XMLStreamException {
 -
 -    Object object = unmarshal(file);
 -
 -    Object requestType = ((JAXBElement) object).getValue();
 -    
 -    assertTrue(requestType instanceof CreateXMLSignatureRequestType);
 -    
 -    List<DataObjectInfoType> dataObjectInfos = ((CreateXMLSignatureRequestType) requestType).getDataObjectInfo();
 -    
 -    assertNotNull(dataObjectInfos);
 -    
 -    return dataObjectInfos;
 -    
 -  }
 -
 -  private void signAndMarshalSignature(Signature signature) throws MarshalException, XMLSignatureException, SLCommandException, SLViewerException {
 -
 -    Node parent = signature.getParent();
 -    Node nextSibling = signature.getNextSibling();
 -    
 -    DOMSignContext signContext = (nextSibling == null) 
 -      ? new DOMSignContext(privateKey, parent)
 -      : new DOMSignContext(privateKey, parent, nextSibling);
 -      
 -    signature.sign(signContext);
 -    
 -    Document document = signature.getDocument();
 -    
 -    DOMImplementationLS domImplLS = DOMUtils.getDOMImplementationLS();
 -    LSOutput output = domImplLS.createLSOutput();
 -    output.setByteStream(System.out);
 -    
 -    LSSerializer serializer = domImplLS.createLSSerializer();
 -//    serializer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE);
 -    serializer.getDomConfig().setParameter("namespaces", Boolean.FALSE);
 -    serializer.write(document, output);
 -    
 -  }
 -
 -  @SuppressWarnings("unchecked")
 -  @Test
 -  public void testDataObject_Base64Content_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException {
 -
 -    List<DataObjectInfoType> dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_Base64Content_1.xml");
 -    
 -    Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl());
 -    
 -    for (DataObjectInfoType dataObjectInfo : dataObjectInfos) {
 -      signature.addDataObject(dataObjectInfo);
 -    }
 -    
 -    signature.setSignerCeritifcate(certificate);
 -    
 -    signature.buildXMLSignature();
 -    
 -    signAndMarshalSignature(signature);
 -    
 -    List<Reference> references = signature.getReferences();
 -    assertTrue(references.size() == 2);
 -
 -    Reference reference = references.get(0);
 -    assertNotNull(reference.getId());
 -    
 -    List<Transform> transforms = reference.getTransforms();
 -    assertTrue(transforms.size() == 1);
 -    
 -    Transform transform = transforms.get(0);
 -    assertTrue(Transform.BASE64.equals(transform.getAlgorithm()));
 -  
 -    List<XMLObject> objects = signature.getXMLObjects();
 -    assertNotNull(objects);
 -    assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2);
 -    
 -    XMLObject object = objects.get(0);
 -    
 -    assertTrue(("#" + object.getId()).equals(reference.getURI()));
 -    
 -  }
 -
 -  @SuppressWarnings("unchecked")
 -  @Test
 -  public void testDataObject_XMLContent_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException {
 -
 -    List<DataObjectInfoType> dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_XMLContent_1.xml");
 -    
 -    Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl());
 -    
 -    for (DataObjectInfoType dataObjectInfo : dataObjectInfos) {
 -      signature.addDataObject(dataObjectInfo);
 -    }
 -    
 -    signature.setSignerCeritifcate(certificate);
 -    
 -    signature.buildXMLSignature();
 -    
 -    signAndMarshalSignature(signature);
 -
 -    List<Reference> references = signature.getReferences();
 -    assertTrue(references.size() == 2);
 -
 -    Reference reference = references.get(0);
 -    assertNotNull(reference.getId());
 -    
 -    List<Transform> transforms = reference.getTransforms();
 -    assertTrue(transforms.size() == 2);
 -    
 -    Transform transform = transforms.get(0);
 -    assertTrue(Transform.XPATH2.equals(transform.getAlgorithm()));
 -  
 -    List<XMLObject> objects = signature.getXMLObjects();
 -    assertNotNull(objects);
 -    assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2);
 -    
 -    XMLObject object = objects.get(0);
 -    
 -    assertTrue(("#" + object.getId()).equals(reference.getURI()));
 -    
 -  }
 -
 -  @SuppressWarnings("unchecked")
 -  @Test
 -  public void testDataObject_XMLContent_2() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException {
 -
 -    List<DataObjectInfoType> dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_XMLContent_2.xml");
 -    
 -    Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl());
 -    
 -    for (DataObjectInfoType dataObjectInfo : dataObjectInfos) {
 -      signature.addDataObject(dataObjectInfo);
 -    }
 -    
 -    signature.setSignerCeritifcate(certificate);
 -    
 -    signature.buildXMLSignature();
 -    
 -    signAndMarshalSignature(signature);
 -
 -    List<Reference> references = signature.getReferences();
 -    assertTrue(references.size() == 2);
 -
 -    Reference reference = references.get(0);
 -    assertNotNull(reference.getId());
 -    
 -    List<Transform> transforms = reference.getTransforms();
 -    assertTrue(transforms.size() == 2);
 -    
 -    Transform transform = transforms.get(0);
 -    assertTrue(Transform.XPATH2.equals(transform.getAlgorithm()));
 -  
 -    List<XMLObject> objects = signature.getXMLObjects();
 -    assertNotNull(objects);
 -    assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2);
 -    
 -    XMLObject object = objects.get(0);
 -    
 -    assertTrue(("#" + object.getId()).equals(reference.getURI()));
 -    
 -  }
 -
 -  
 -  @SuppressWarnings("unchecked")
 -  @Test
 -  public void testDataObject_LocRefContent_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException {
 -
 -    List<DataObjectInfoType> dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_LocRefContent_1.xml");
 -    
 -    Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl());
 -    
 -    for (DataObjectInfoType dataObjectInfo : dataObjectInfos) {
 -      signature.addDataObject(dataObjectInfo);
 -    }
 -    
 -    signature.buildXMLSignature();
 -    
 -    signAndMarshalSignature(signature);
 -
 -    List<Reference> references = signature.getReferences();
 -    assertTrue(references.size() == 2);
 -
 -    Reference reference = references.get(0);
 -    assertNotNull(reference.getId());
 -    
 -    List<Transform> transforms = reference.getTransforms();
 -    assertTrue(transforms.size() == 2);
 -    
 -    Transform transform = transforms.get(0);
 -    assertTrue(Transform.XPATH2.equals(transform.getAlgorithm()));
 -  
 -    List<XMLObject> objects = signature.getXMLObjects();
 -    assertNotNull(objects);
 -    assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2);
 -    
 -    XMLObject object = objects.get(0);
 -    
 -    assertTrue(("#" + object.getId()).equals(reference.getURI()));
 -    
 -  }
 -
 -  @SuppressWarnings("unchecked")
 -  @Test
 -  public void testDataObject_LocRefContent_2() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException {
 -
 -    List<DataObjectInfoType> dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_LocRefContent_2.xml");
 -    
 -    Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl());
 -    
 -    for (DataObjectInfoType dataObjectInfo : dataObjectInfos) {
 -      signature.addDataObject(dataObjectInfo);
 -    }
 -    
 -    signature.buildXMLSignature();
 -    
 -    signAndMarshalSignature(signature);
 -    
 -    List<Reference> references = signature.getReferences();
 -    assertTrue(references.size() == 2);
 -
 -    Reference reference = references.get(0);
 -    assertNotNull(reference.getId());
 -    
 -    List<Transform> transforms = reference.getTransforms();
 -    assertTrue(transforms.size() == 1);
 -    
 -    Transform transform = transforms.get(0);
 -    assertTrue(Transform.BASE64.equals(transform.getAlgorithm()));
 -  
 -    List<XMLObject> objects = signature.getXMLObjects();
 -    assertNotNull(objects);
 -    assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2);
 -    
 -    XMLObject object = objects.get(0);
 -    
 -    assertTrue(("#" + object.getId()).equals(reference.getURI()));
 -    
 -  }
 -
 -  @SuppressWarnings("unchecked")
 -  @Test
 -  public void testDataObject_Reference_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException {
 -
 -    List<DataObjectInfoType> dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_Reference_1.xml");
 -    
 -    Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl());
 -    
 -    for (DataObjectInfoType dataObjectInfo : dataObjectInfos) {
 -      signature.addDataObject(dataObjectInfo);
 -    }
 -    
 -    signature.buildXMLSignature();
 -    
 -    signAndMarshalSignature(signature);
 -    
 -    List<Reference> references = signature.getReferences();
 -    assertTrue(references.size() == 2);
 -
 -    Reference reference = references.get(0);
 -    assertNotNull(reference.getId());
 -    
 -    List<Transform> transforms = reference.getTransforms();
 -    assertTrue(transforms.size() == 1);
 -    
 -    Transform transform = transforms.get(0);
 -    assertTrue(Transform.BASE64.equals(transform.getAlgorithm()));
 -  
 -    List<XMLObject> objects = signature.getXMLObjects();
 -    assertNotNull(objects);
 -    assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2);
 -    
 -    XMLObject object = objects.get(0);
 -    
 -    assertTrue(("#" + object.getId()).equals(reference.getURI()));
 -    
 -  }
 -
 -  @SuppressWarnings("unchecked")
 -  @Test
 -  public void testDataObject_Detached_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException {
 -
 -    List<DataObjectInfoType> dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_Detached_1.xml");
 -    
 -    Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl());
 -    
 -    for (DataObjectInfoType dataObjectInfo : dataObjectInfos) {
 -      signature.addDataObject(dataObjectInfo);
 -    }
 -    
 -    signature.buildXMLSignature();
 -    
 -    signAndMarshalSignature(signature);
 -    
 -    List<Reference> references = signature.getReferences();
 -    assertTrue(references.size() == 2);
 -
 -    Reference reference = references.get(0);
 -    assertNotNull(reference.getId());
 -    
 -    List<Transform> transforms = reference.getTransforms();
 -    assertTrue(transforms.size() == 0);
 -    
 -    List<XMLObject> objects = signature.getXMLObjects();
 -    assertNotNull(objects);
 -    assertTrue(objects.size() == 1);
 -    
 -  }
 -  
 -  @SuppressWarnings("unchecked")
 -  @Test
 -  public void testDataObject_Detached_Base64Content() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException {
 -
 -    List<DataObjectInfoType> dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_Detached_Base64Content.xml");
 -    
 -    Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl());
 -    
 -    for (DataObjectInfoType dataObjectInfo : dataObjectInfos) {
 -      signature.addDataObject(dataObjectInfo);
 -    }
 -    
 -    signature.buildXMLSignature();
 -    
 -    signAndMarshalSignature(signature);
 -    
 -    List<Reference> references = signature.getReferences();
 -    assertTrue(references.size() == 2);
 -
 -    Reference reference = references.get(0);
 -    assertNotNull(reference.getId());
 -    
 -    List<Transform> transforms = reference.getTransforms();
 -    assertTrue(transforms.size() == 0);
 -    
 -    List<XMLObject> objects = signature.getXMLObjects();
 -    assertNotNull(objects);
 -    assertTrue(objects.size() == 1);
 -    
 -  }
 -  
 -  //
 -  //
 -  // TransformsInfo
 -  //
 -  //
 -  
 -  @SuppressWarnings("unchecked")
 -  private CreateXMLSignatureRequestType unmarshalCreateXMLSignatureRequest(String file) throws JAXBException, XMLStreamException {
 -
 -    Object object = unmarshal(file);
 -
 -    Object requestType = ((JAXBElement) object).getValue();
 -    
 -    assertTrue(requestType instanceof CreateXMLSignatureRequestType);
 -    
 -    return (CreateXMLSignatureRequestType) requestType;
 -    
 -  }
 -
 -  
 -  @SuppressWarnings("unchecked")
 -  @Test
 -  public void testTransformsInfo_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException {
 -
 -    CreateXMLSignatureRequestType requestType = unmarshalCreateXMLSignatureRequest("TransformsInfo_1.xml");
 -    
 -    Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl());
 -
 -
 -    signature.setSignatureInfo(requestType.getSignatureInfo());
 -    
 -    List<DataObjectInfoType> dataObjectInfos = requestType.getDataObjectInfo();
 -    
 -    for (DataObjectInfoType dataObjectInfo : dataObjectInfos) {
 -      signature.addDataObject(dataObjectInfo);
 -    }
 -    
 -    signature.setSignerCeritifcate(certificate);
 -    
 -    signature.buildXMLSignature();
 -    
 -    signAndMarshalSignature(signature);
 -    
 -    List<Reference> references = signature.getReferences();
 -    assertTrue(references.size() == 2);
 -
 -    Reference reference = references.get(0);
 -    assertNotNull(reference.getId());
 -    
 -    List<Transform> transforms = reference.getTransforms();
 -    assertTrue("Size " + transforms.size() + "", transforms.size() == 3);
 -    
 -    Transform transform = transforms.get(0);
 -    assertTrue(Transform.ENVELOPED.equals(transform.getAlgorithm()));
 -  
 -    List<XMLObject> objects = signature.getXMLObjects();
 -    assertNotNull(objects);
 -    assertTrue("Size " + objects.size() + " but should be 1.", objects.size() == 1);
 -    
 -  }
 -
 -  
 -}
 +      } +       +    }); +     +  } +   +  private Object unmarshal(String file) throws XMLStreamException, JAXBException { + +    ClassLoader classLoader = SignatureTest.class.getClassLoader(); +    InputStream resourceStream = classLoader.getResourceAsStream(RESOURCE_PREFIX + file); +    assertNotNull(resourceStream); + +    XMLInputFactory inputFactory = XMLInputFactory.newInstance(); +    XMLEventReader eventReader = inputFactory.createXMLEventReader(resourceStream); +    RedirectEventFilter redirectEventFilter = new RedirectEventFilter(); +    XMLEventReader filteredReader = inputFactory.createFilteredReader(eventReader, redirectEventFilter); + +    unmarshaller.setListener(new RedirectUnmarshallerListener(redirectEventFilter)); + +    return unmarshaller.unmarshal(filteredReader); +     +  } +   +  // +  // +  // SignatureInfo +  // +  // +   +  @SuppressWarnings("unchecked") +  private SignatureInfoCreationType unmarshalSignatureInfo(String file) throws JAXBException, XMLStreamException { + +    Object object = unmarshal(file); + +    Object requestType = ((JAXBElement) object).getValue(); +     +    assertTrue(requestType instanceof CreateXMLSignatureRequestType); +     +    SignatureInfoCreationType signatureInfo = ((CreateXMLSignatureRequestType) requestType).getSignatureInfo();  +     +    assertNotNull(signatureInfo); +     +    return signatureInfo; +     +  } + +  @Test +  public void testSetSignatureInfo_Base64_1() throws JAXBException, SLCommandException, XMLStreamException { + +    SignatureInfoCreationType signatureInfo = unmarshalSignatureInfo("SignatureInfo_Base64_1.xml"); +     +    Signature signature = new Signature(null, new IdValueFactoryImpl(), null); +     +    signature.setSignatureInfo(signatureInfo); +     +    Node parent = signature.getParent(); +    Node nextSibling = signature.getNextSibling(); + +    assertNotNull(parent); +    assertTrue("urn:document".equals(parent.getNamespaceURI())); +    assertTrue("XMLDocument".equals(parent.getLocalName())); +     +    assertNotNull(nextSibling); +    assertTrue("urn:document".equals(nextSibling.getNamespaceURI())); +    assertTrue("Paragraph".equals(nextSibling.getLocalName())); +     +  } + +  @Test +  public void testSetSignature_Base64_2() throws JAXBException, SLCommandException, XMLStreamException { + +    SignatureInfoCreationType signatureInfo = unmarshalSignatureInfo("SignatureInfo_Base64_2.xml"); +     +    Signature signature = new Signature(null, new IdValueFactoryImpl(), null); +     +    signature.setSignatureInfo(signatureInfo); +     +    Node parent = signature.getParent(); +    Node nextSibling = signature.getNextSibling(); + +    assertNotNull(parent); +    assertTrue("XMLDocument".equals(parent.getLocalName())); +     +    assertNotNull(nextSibling); +    assertTrue("Paragraph".equals(nextSibling.getLocalName())); +     +  } + +  @Test +  public void testSetSignature_Base64_3() throws JAXBException, SLCommandException, XMLStreamException { + +    SignatureInfoCreationType signatureInfo = unmarshalSignatureInfo("SignatureInfo_Base64_3.xml"); +     +    Signature signature = new Signature(null, new IdValueFactoryImpl(), null); +     +    signature.setSignatureInfo(signatureInfo); +     +    Node parent = signature.getParent(); +    Node nextSibling = signature.getNextSibling(); + +    assertNotNull(parent); +    assertTrue("XMLDocument".equals(parent.getLocalName())); +     +    assertNotNull(nextSibling); +    assertTrue("Paragraph".equals(nextSibling.getLocalName())); +     +  } + +  @Test +  public void testSetSignatureInfo_XMLContent_1() throws JAXBException, SLCommandException, XMLStreamException { + +    SignatureInfoCreationType signatureInfo = unmarshalSignatureInfo("SignatureInfo_XMLContent_1.xml"); +     +    Signature signature = new Signature(null, new IdValueFactoryImpl(), null); +     +    signature.setSignatureInfo(signatureInfo); +     +    Node parent = signature.getParent(); +    Node nextSibling = signature.getNextSibling(); +     +    assertNotNull(parent); +    assertTrue("urn:document".equals(parent.getNamespaceURI())); +    assertTrue("Whole".equals(parent.getLocalName())); +     +    assertNull(nextSibling); +     +  } + +  @Test +  public void testSetSignature_Reference_1() throws JAXBException, SLCommandException, XMLStreamException { + +    SignatureInfoCreationType signatureInfo = unmarshalSignatureInfo("SignatureInfo_Reference_1.xml"); +     +    Signature signature = new Signature(null, new IdValueFactoryImpl(), null); +     +    signature.setSignatureInfo(signatureInfo); +     +    Node parent = signature.getParent(); +    Node nextSibling = signature.getNextSibling(); +     +    assertNotNull(parent); +    assertTrue("urn:document".equals(parent.getNamespaceURI())); +    assertTrue("Paragraph".equals(parent.getLocalName())); +     +    assertNull(nextSibling); +     +  } + +  // +  // +  // DataObject +  // +  // + +  @SuppressWarnings("unchecked") +  private List<DataObjectInfoType> unmarshalDataObjectInfo(String file) throws JAXBException, XMLStreamException { + +    Object object = unmarshal(file); + +    Object requestType = ((JAXBElement) object).getValue(); +     +    assertTrue(requestType instanceof CreateXMLSignatureRequestType); +     +    List<DataObjectInfoType> dataObjectInfos = ((CreateXMLSignatureRequestType) requestType).getDataObjectInfo(); +     +    assertNotNull(dataObjectInfos); +     +    return dataObjectInfos; +     +  } + +  private void signAndMarshalSignature(Signature signature) throws MarshalException, XMLSignatureException, SLCommandException, SLViewerException { + +    Node parent = signature.getParent(); +    Node nextSibling = signature.getNextSibling(); +     +    DOMSignContext signContext = (nextSibling == null)  +      ? new DOMSignContext(privateKey, parent) +      : new DOMSignContext(privateKey, parent, nextSibling); +       +    signature.sign(signContext); +     +    Document document = signature.getDocument(); +     +    DOMImplementationLS domImplLS = DOMUtils.getDOMImplementationLS(); +    LSOutput output = domImplLS.createLSOutput(); +    output.setByteStream(System.out); +     +    LSSerializer serializer = domImplLS.createLSSerializer(); +//    serializer.getDomConfig().setParameter("format-pretty-print", Boolean.TRUE); +    serializer.getDomConfig().setParameter("namespaces", Boolean.FALSE); +    serializer.write(document, output); +     +  } + +  @SuppressWarnings("unchecked") +  @Test +  public void testDataObject_Base64Content_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { + +    List<DataObjectInfoType> dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_Base64Content_1.xml"); +     +    Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); +     +    for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { +      signature.addDataObject(dataObjectInfo); +    } +     +    signature.setSignerCeritifcate(certificate); +     +    signature.buildXMLSignature(); +     +    signAndMarshalSignature(signature); +     +    List<Reference> references = signature.getReferences(); +    assertTrue(references.size() == 2); + +    Reference reference = references.get(0); +    assertNotNull(reference.getId()); +     +    List<Transform> transforms = reference.getTransforms(); +    assertTrue(transforms.size() == 1); +     +    Transform transform = transforms.get(0); +    assertTrue(Transform.BASE64.equals(transform.getAlgorithm())); +   +    List<XMLObject> objects = signature.getXMLObjects(); +    assertNotNull(objects); +    assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2); +     +    XMLObject object = objects.get(0); +     +    assertTrue(("#" + object.getId()).equals(reference.getURI())); +     +  } + +  @SuppressWarnings("unchecked") +  @Test +  public void testDataObject_XMLContent_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { + +    List<DataObjectInfoType> dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_XMLContent_1.xml"); +     +    Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); +     +    for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { +      signature.addDataObject(dataObjectInfo); +    } +     +    signature.setSignerCeritifcate(certificate); +     +    signature.buildXMLSignature(); +     +    signAndMarshalSignature(signature); + +    List<Reference> references = signature.getReferences(); +    assertTrue(references.size() == 2); + +    Reference reference = references.get(0); +    assertNotNull(reference.getId()); +     +    List<Transform> transforms = reference.getTransforms(); +    assertTrue(transforms.size() == 2); +     +    Transform transform = transforms.get(0); +    assertTrue(Transform.XPATH2.equals(transform.getAlgorithm())); +   +    List<XMLObject> objects = signature.getXMLObjects(); +    assertNotNull(objects); +    assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2); +     +    XMLObject object = objects.get(0); +     +    assertTrue(("#" + object.getId()).equals(reference.getURI())); +     +  } + +  @SuppressWarnings("unchecked") +  @Test +  public void testDataObject_XMLContent_2() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { + +    List<DataObjectInfoType> dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_XMLContent_2.xml"); +     +    Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); +     +    for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { +      signature.addDataObject(dataObjectInfo); +    } +     +    signature.setSignerCeritifcate(certificate); +     +    signature.buildXMLSignature(); +     +    signAndMarshalSignature(signature); + +    List<Reference> references = signature.getReferences(); +    assertTrue(references.size() == 2); + +    Reference reference = references.get(0); +    assertNotNull(reference.getId()); +     +    List<Transform> transforms = reference.getTransforms(); +    assertTrue(transforms.size() == 2); +     +    Transform transform = transforms.get(0); +    assertTrue(Transform.XPATH2.equals(transform.getAlgorithm())); +   +    List<XMLObject> objects = signature.getXMLObjects(); +    assertNotNull(objects); +    assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2); +     +    XMLObject object = objects.get(0); +     +    assertTrue(("#" + object.getId()).equals(reference.getURI())); +     +  } + +   +  @SuppressWarnings("unchecked") +  @Test +  public void testDataObject_LocRefContent_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { + +    List<DataObjectInfoType> dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_LocRefContent_1.xml"); +     +    Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); +     +    for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { +      signature.addDataObject(dataObjectInfo); +    } +     +    signature.buildXMLSignature(); +     +    signAndMarshalSignature(signature); + +    List<Reference> references = signature.getReferences(); +    assertTrue(references.size() == 2); + +    Reference reference = references.get(0); +    assertNotNull(reference.getId()); +     +    List<Transform> transforms = reference.getTransforms(); +    assertTrue(transforms.size() == 2); +     +    Transform transform = transforms.get(0); +    assertTrue(Transform.XPATH2.equals(transform.getAlgorithm())); +   +    List<XMLObject> objects = signature.getXMLObjects(); +    assertNotNull(objects); +    assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2); +     +    XMLObject object = objects.get(0); +     +    assertTrue(("#" + object.getId()).equals(reference.getURI())); +     +  } + +  @SuppressWarnings("unchecked") +  @Test +  public void testDataObject_LocRefContent_2() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { + +    List<DataObjectInfoType> dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_LocRefContent_2.xml"); +     +    Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); +     +    for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { +      signature.addDataObject(dataObjectInfo); +    } +     +    signature.buildXMLSignature(); +     +    signAndMarshalSignature(signature); +     +    List<Reference> references = signature.getReferences(); +    assertTrue(references.size() == 2); + +    Reference reference = references.get(0); +    assertNotNull(reference.getId()); +     +    List<Transform> transforms = reference.getTransforms(); +    assertTrue(transforms.size() == 1); +     +    Transform transform = transforms.get(0); +    assertTrue(Transform.BASE64.equals(transform.getAlgorithm())); +   +    List<XMLObject> objects = signature.getXMLObjects(); +    assertNotNull(objects); +    assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2); +     +    XMLObject object = objects.get(0); +     +    assertTrue(("#" + object.getId()).equals(reference.getURI())); +     +  } + +  @SuppressWarnings("unchecked") +  @Test +  public void testDataObject_Reference_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { + +    List<DataObjectInfoType> dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_Reference_1.xml"); +     +    Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); +     +    for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { +      signature.addDataObject(dataObjectInfo); +    } +     +    signature.buildXMLSignature(); +     +    signAndMarshalSignature(signature); +     +    List<Reference> references = signature.getReferences(); +    assertTrue(references.size() == 2); + +    Reference reference = references.get(0); +    assertNotNull(reference.getId()); +     +    List<Transform> transforms = reference.getTransforms(); +    assertTrue(transforms.size() == 1); +     +    Transform transform = transforms.get(0); +    assertTrue(Transform.BASE64.equals(transform.getAlgorithm())); +   +    List<XMLObject> objects = signature.getXMLObjects(); +    assertNotNull(objects); +    assertTrue("Size " + objects.size() + " but should be 2.", objects.size() == 2); +     +    XMLObject object = objects.get(0); +     +    assertTrue(("#" + object.getId()).equals(reference.getURI())); +     +  } + +  @SuppressWarnings("unchecked") +  @Test +  public void testDataObject_Detached_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { + +    List<DataObjectInfoType> dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_Detached_1.xml"); +     +    Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); +     +    for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { +      signature.addDataObject(dataObjectInfo); +    } +     +    signature.buildXMLSignature(); +     +    signAndMarshalSignature(signature); +     +    List<Reference> references = signature.getReferences(); +    assertTrue(references.size() == 2); + +    Reference reference = references.get(0); +    assertNotNull(reference.getId()); +     +    List<Transform> transforms = reference.getTransforms(); +    assertTrue(transforms.size() == 0); +     +    List<XMLObject> objects = signature.getXMLObjects(); +    assertNotNull(objects); +    assertTrue(objects.size() == 1); +     +  } +   +  @SuppressWarnings("unchecked") +  @Test +  public void testDataObject_Detached_Base64Content() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { + +    List<DataObjectInfoType> dataObjectInfos = unmarshalDataObjectInfo("DataObjectInfo_Detached_Base64Content.xml"); +     +    Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); +     +    for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { +      signature.addDataObject(dataObjectInfo); +    } +     +    signature.buildXMLSignature(); +     +    signAndMarshalSignature(signature); +     +    List<Reference> references = signature.getReferences(); +    assertTrue(references.size() == 2); + +    Reference reference = references.get(0); +    assertNotNull(reference.getId()); +     +    List<Transform> transforms = reference.getTransforms(); +    assertTrue(transforms.size() == 0); +     +    List<XMLObject> objects = signature.getXMLObjects(); +    assertNotNull(objects); +    assertTrue(objects.size() == 1); +     +  } +   +  // +  // +  // TransformsInfo +  // +  // +   +  @SuppressWarnings("unchecked") +  private CreateXMLSignatureRequestType unmarshalCreateXMLSignatureRequest(String file) throws JAXBException, XMLStreamException { + +    Object object = unmarshal(file); + +    Object requestType = ((JAXBElement) object).getValue(); +     +    assertTrue(requestType instanceof CreateXMLSignatureRequestType); +     +    return (CreateXMLSignatureRequestType) requestType; +     +  } + +   +  @SuppressWarnings("unchecked") +  @Test +  public void testTransformsInfo_1() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { + +    CreateXMLSignatureRequestType requestType = unmarshalCreateXMLSignatureRequest("TransformsInfo_1.xml"); +     +    Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); + + +    signature.setSignatureInfo(requestType.getSignatureInfo()); +     +    List<DataObjectInfoType> dataObjectInfos = requestType.getDataObjectInfo(); +     +    for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { +      signature.addDataObject(dataObjectInfo); +    } +     +    signature.setSignerCeritifcate(certificate); +     +    signature.buildXMLSignature(); +     +    signAndMarshalSignature(signature); +     +    List<Reference> references = signature.getReferences(); +    assertTrue(references.size() == 2); + +    Reference reference = references.get(0); +    assertNotNull(reference.getId()); +     +    List<Transform> transforms = reference.getTransforms(); +    assertTrue("Size " + transforms.size() + "", transforms.size() == 3); +     +    Transform transform = transforms.get(0); +    assertTrue(Transform.ENVELOPED.equals(transform.getAlgorithm())); +   +    List<XMLObject> objects = signature.getXMLObjects(); +    assertNotNull(objects); +    assertTrue("Size " + objects.size() + " but should be 1.", objects.size() == 1); +     +  } + +  @SuppressWarnings("unchecked") +  @Test +  @Ignore +  public void testTransformsInfo_2() throws JAXBException, SLCommandException, XMLStreamException, SLRequestException, MarshalException, XMLSignatureException, SLViewerException { + +    CreateXMLSignatureRequestType requestType = unmarshalCreateXMLSignatureRequest("TransformsInfo_2.xml"); + +    Signature signature = new Signature(null, new IdValueFactoryImpl(), new AlgorithmMethodFactoryImpl()); + + +    signature.setSignatureInfo(requestType.getSignatureInfo()); + +    List<DataObjectInfoType> dataObjectInfos = requestType.getDataObjectInfo(); + +    for (DataObjectInfoType dataObjectInfo : dataObjectInfos) { +      signature.addDataObject(dataObjectInfo); +    } + +    signature.setSignerCeritifcate(certificate); + +    signature.buildXMLSignature(); + +    signAndMarshalSignature(signature); + +    List<Reference> references = signature.getReferences(); +    assertTrue(references.size() == 2); + +    Reference reference = references.get(0); +    assertNotNull(reference.getId()); + +    List<Transform> transforms = reference.getTransforms(); +    assertTrue("Size " + transforms.size() + "", transforms.size() == 2); + +    Transform transform = transforms.get(0); +    assertTrue(Transform.XSLT.equals(transform.getAlgorithm())); + +    List<XMLObject> objects = signature.getXMLObjects(); +    assertNotNull(objects); +    assertTrue("Size " + objects.size() + " but should be 1.", objects.size() == 1); + +  } + +   +} diff --git a/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/impl/TransformsInfo_2.xml b/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/impl/TransformsInfo_2.xml new file mode 100644 index 00000000..f43dc61a --- /dev/null +++ b/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/impl/TransformsInfo_2.xml @@ -0,0 +1,397 @@ +<?xml version="1.0" encoding="UTF-8" ?>
 +<sl:CreateXMLSignatureRequest xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"
 +	xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#">
 +	<sl:KeyboxIdentifier>SecureSignatureKeypair</sl:KeyboxIdentifier>
 +	<sl:DataObjectInfo Structure="detached">
 +		<sl:DataObject Reference=""/>
 +		<sl:TransformsInfo>
 +			<dsig:Transforms xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
 +				<dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
 +				<dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116">
 +					<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 +						xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion"
 +						xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#">
 +						<xsl:template match="/" xmlns="http://www.w3.org/1999/xhtml">
 +							<html>
 +								<head>
 +									<title>Signatur der Anmeldedaten</title>
 +									<style type="text/css" media="screen">
 +							.boldstyle { font-weight: bold; }
 +							.italicstyle { font-style: italic; }
 +							.annotationstyle { font-size: 0.8em; }
 +							</style>
 +								</head>
 +								<body>
 +									<h1>Signatur der Anmeldedaten</h1>
 +									<p/>
 +									<h4>Mit meiner elektronischen Signatur beantrage ich, <span
 +											class="boldstyle">
 +											<xsl:value-of select="//@Issuer"/>
 +										</span>, geboren am <xsl:value-of
 +											select="substring(//saml:Attribute[@AttributeName='Geburtsdatum']/saml:AttributeValue,9,2)"
 +										/>. <xsl:value-of
 +											select="substring(//saml:Attribute[@AttributeName='Geburtsdatum']/saml:AttributeValue,6,2)"
 +										/>. <xsl:value-of
 +											select="substring(//saml:Attribute[@AttributeName='Geburtsdatum']/saml:AttributeValue,1,4)"
 +										/>, <xsl:if
 +											test="//saml:Attribute[@AttributeName='OIDTextualDescription']"
 +											> in der Rolle als <xsl:value-of
 +												select="//saml:Attribute[@AttributeName='OIDTextualDescription']/saml:AttributeValue"
 +											/> (OID***= <xsl:value-of
 +												select="//saml:Attribute[@AttributeName='OID']/saml:AttributeValue"
 +											/>), </xsl:if> den Zugang zur gesicherten Anwendung. </h4>
 +									<p/>
 +									<h4>Datum und Uhrzeit: <xsl:value-of
 +											select="substring(//@IssueInstant,9,2)"/>. <xsl:value-of
 +											select="substring(//@IssueInstant,6,2)"/>. <xsl:value-of
 +											select="substring(//@IssueInstant,1,4)"/>, <xsl:value-of
 +											select="substring(//@IssueInstant,12,2)"/>:
 +											<xsl:value-of select="substring(//@IssueInstant,15,2)"
 +										/>: <xsl:value-of select="substring(//@IssueInstant,18,2)"/>
 +									</h4>
 +									<xsl:if test="//saml:Attribute[@AttributeName='HPI']">
 +										<h4>HPI(**): <xsl:value-of
 +												select="//saml:Attribute[@AttributeName='HPI']/saml:AttributeValue"
 +											/></h4>
 +									</xsl:if>
 +									<xsl:if test="//saml:Attribute[@AttributeName='wbPK']">
 +										<h4>wbPK(*): <xsl:value-of
 +												select="//saml:Attribute[@AttributeName='wbPK']/saml:AttributeValue/pr:Identification/pr:Value"
 +											/></h4>
 +									</xsl:if>
 +									<xsl:if test="//saml:Attribute[@AttributeName='MandatorName']">
 +										<hr/>
 +										<h4>Ich bin weiters ermächtigt als <xsl:value-of
 +												select="//saml:Attribute[@AttributeName='RepresentationType']/saml:AttributeValue/text()"
 +											/> von <xsl:value-of
 +												select="//saml:Attribute[@AttributeName='MandatorName']/saml:AttributeValue/text()"/>
 +											<xsl:if
 +												test="//saml:Attribute[@AttributeName='MandatorDateOfBirth']"
 +												>, geboren am <xsl:value-of
 +												select="substring(//saml:Attribute[@AttributeName='MandatorDateOfBirth']/saml:AttributeValue,9,2)"
 +												/>. <xsl:value-of
 +												select="substring(//saml:Attribute[@AttributeName='MandatorDateOfBirth']/saml:AttributeValue,6,2)"
 +												/>. <xsl:value-of
 +												select="substring(//saml:Attribute[@AttributeName='MandatorDateOfBirth']/saml:AttributeValue,1,4)"
 +												/>
 +											</xsl:if>
 +											<xsl:if
 +												test="//saml:Attribute[@AttributeName='MandatorDomainIdentifier']"
 +												>, <xsl:value-of
 +												select="//saml:Attribute[@AttributeName='MandatorDomainIdentifier']/saml:AttributeValue/text()"
 +												/>
 +											</xsl:if>, in deren Auftrag zu handeln. <xsl:if
 +												test="//saml:Attribute[@AttributeName='MandatorWbpk']">
 +												<h4>wbPK(*) des Vollmachtgebers: <xsl:value-of
 +												select="//saml:Attribute[@AttributeName='MandatorWbpk']/saml:AttributeValue/text()"
 +												/></h4>
 +											</xsl:if>
 +										</h4>
 +										<p/>
 +									</xsl:if>
 +									<xsl:choose>
 +										<xsl:when test="//saml:Attribute[@AttributeName='OID']">
 +											<p/>
 +											<hr/>
 +										</xsl:when>
 +										<xsl:when test="//saml:Attribute[@AttributeName='HPI']">
 +											<p/>
 +											<hr/>
 +										</xsl:when>
 +										<xsl:when test="//saml:Attribute[@AttributeName='wbPK']">
 +											<p/>
 +											<hr/>
 +										</xsl:when>
 +									</xsl:choose>
 +									<xsl:if test="//saml:Attribute[@AttributeName='wbPK']">
 +										<div class="annotationstyle">(*) wbPK: Das <span
 +												class="italicstyle">wirtschaftsbereichsspezifische
 +												Personenkennzeichen</span> wird aus den jeweiligen
 +											Stammzahlen des Bürgers und des Wirtschaftsunternehmens
 +											berechnet und ermöglicht eine eindeutige Zuordnung des
 +											Bürgers zum Wirtschaftsunternehmen.</div>
 +									</xsl:if>
 +									<xsl:if test="//saml:Attribute[@AttributeName='HPI']">
 +										<div class="annotationstyle">(**) HPI: Der <span
 +												class="italicstyle">eHealth Professional
 +											Identifier</span> wird aus den jeweiligen Stammzahlen
 +											der Gesundheitsdiensteanbieterinnen /
 +											Gesundheitsdiensteanbieter berechnet und ermöglicht eine
 +											eindeutige Zuordnung der Gesundheitsdiensteanbieterin /
 +											des Gesundheitsdiensteanbieters im
 +										Gesundheitsbereich.</div>
 +									</xsl:if>
 +									<xsl:if test="//saml:Attribute[@AttributeName='OID']">
 +										<div class="annotationstyle">(***) OID: <span
 +												class="italicstyle">Object Identifier</span> sind
 +											standardisierte Objekt-Bezeichner und beschreiben
 +											eindeutig die Rollen des GDA-Token Inhabers.</div>
 +									</xsl:if>
 +								</body>
 +							</html>
 +						</xsl:template>
 +					</xsl:stylesheet>
 +				</dsig:Transform>
 +				<dsig:Transform
 +					Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
 +			</dsig:Transforms>
 +			<sl:FinalDataMetaInfo>
 +				<sl:MimeType>application/xhtml+xml</sl:MimeType>
 +			</sl:FinalDataMetaInfo>
 +		</sl:TransformsInfo>
 +		<sl:TransformsInfo>
 +			<dsig:Transforms xmlns:dsig="http://www.w3.org/2000/09/xmldsig#">
 +				<dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
 +				<dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116">
 +					<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
 +						xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion"
 +						xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#">
 +						<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
 +						<xsl:template match="/" xmlns="http://www.w3.org/1999/xhtml">
 +							<html>
 +								<head>
 +									<title>Signatur der Anmeldedaten</title>
 +								</head>
 +								<body>
 +									<h1>Signatur der Anmeldedaten</h1>
 +									<p/>
 +									<h4>Mit meiner elektronischen Signatur beantrage ich, <b>
 +											<xsl:value-of select="//@Issuer"/>
 +										</b>, geboren am <xsl:value-of
 +											select="substring(//saml:Attribute[@AttributeName='Geburtsdatum']/saml:AttributeValue,9,2)"
 +										/>. <xsl:value-of
 +											select="substring(//saml:Attribute[@AttributeName='Geburtsdatum']/saml:AttributeValue,6,2)"
 +										/>. <xsl:value-of
 +											select="substring(//saml:Attribute[@AttributeName='Geburtsdatum']/saml:AttributeValue,1,4)"
 +										/>, <xsl:if
 +											test="//saml:Attribute[@AttributeName='OIDTextualDescription']"
 +											> in der Rolle als <xsl:value-of
 +												select="//saml:Attribute[@AttributeName='OIDTextualDescription']/saml:AttributeValue"
 +											/> (OID***= <xsl:value-of
 +												select="//saml:Attribute[@AttributeName='OID']/saml:AttributeValue"
 +											/>), </xsl:if> den Zugang zur gesicherten Anwendung. </h4>
 +									<p/>
 +									<h4>Datum und Uhrzeit: <xsl:value-of
 +											select="substring(//@IssueInstant,9,2)"/>. <xsl:value-of
 +											select="substring(//@IssueInstant,6,2)"/>. <xsl:value-of
 +											select="substring(//@IssueInstant,1,4)"/>, <xsl:value-of
 +											select="substring(//@IssueInstant,12,2)"/>:
 +											<xsl:value-of select="substring(//@IssueInstant,15,2)"
 +										/>: <xsl:value-of select="substring(//@IssueInstant,18,2)"/>
 +									</h4>
 +									<xsl:if test="//saml:Attribute[@AttributeName='HPI']">
 +										<h4>HPI(**): <xsl:value-of
 +												select="//saml:Attribute[@AttributeName='HPI']/saml:AttributeValue"
 +											/></h4>
 +									</xsl:if>
 +									<xsl:if test="//saml:Attribute[@AttributeName='wbPK']">
 +										<h4>wbPK(*): <xsl:value-of
 +												select="//saml:Attribute[@AttributeName='wbPK']/saml:AttributeValue/pr:Identification/pr:Value"
 +											/></h4>
 +									</xsl:if>
 +									<xsl:if test="//saml:Attribute[@AttributeName='MandatorName']">
 +										<hr/>
 +										<h4>Ich bin weiters ermächtigt als <xsl:value-of
 +												select="//saml:Attribute[@AttributeName='RepresentationType']/saml:AttributeValue/text()"
 +											/> von <xsl:value-of
 +												select="//saml:Attribute[@AttributeName='MandatorName']/saml:AttributeValue/text()"/>
 +											<xsl:if
 +												test="//saml:Attribute[@AttributeName='MandatorDateOfBirth']"
 +												>, geboren am <xsl:value-of
 +												select="substring(//saml:Attribute[@AttributeName='MandatorDateOfBirth']/saml:AttributeValue,9,2)"
 +												/>. <xsl:value-of
 +												select="substring(//saml:Attribute[@AttributeName='MandatorDateOfBirth']/saml:AttributeValue,6,2)"
 +												/>. <xsl:value-of
 +												select="substring(//saml:Attribute[@AttributeName='MandatorDateOfBirth']/saml:AttributeValue,1,4)"
 +												/>
 +											</xsl:if>
 +											<xsl:if
 +												test="//saml:Attribute[@AttributeName='MandatorDomainIdentifier']"
 +												>, <xsl:value-of
 +												select="//saml:Attribute[@AttributeName='MandatorDomainIdentifier']/saml:AttributeValue/text()"
 +												/>
 +											</xsl:if>, in deren Auftrag zu handeln. <xsl:if
 +												test="//saml:Attribute[@AttributeName='MandatorWbpk']">
 +												<h4>wbPK(*) des Vollmachtgebers: <xsl:value-of
 +												select="//saml:Attribute[@AttributeName='MandatorWbpk']/saml:AttributeValue/text()"
 +												/></h4>
 +											</xsl:if>
 +										</h4>
 +										<p/>
 +									</xsl:if>
 +									<xsl:choose>
 +										<xsl:when test="//saml:Attribute[@AttributeName='OID']">
 +											<p/>
 +											<hr/>
 +										</xsl:when>
 +										<xsl:when test="//saml:Attribute[@AttributeName='HPI']">
 +											<p/>
 +											<hr/>
 +										</xsl:when>
 +										<xsl:when test="//saml:Attribute[@AttributeName='wbPK']">
 +											<p/>
 +											<hr/>
 +										</xsl:when>
 +									</xsl:choose>
 +									<xsl:if test="//saml:Attribute[@AttributeName='wbPK']">
 +										<h6>(*) wbPK: Das <i>wirtschaftsbereichsspezifische
 +												Personenkennzeichen</i> wird aus den jeweiligen
 +											Stammzahlen des Bürgers und des Wirtschaftsunternehmens
 +											berechnet und ermöglicht eine eindeutige Zuordnung des
 +											Bürgers zum Wirtschaftsunternehmen.</h6>
 +									</xsl:if>
 +									<xsl:if test="//saml:Attribute[@AttributeName='HPI']">
 +										<h6>(**) HPI: Der <i>eHealth Professional Identifier</i>
 +											wird aus den jeweiligen Stammzahlen der
 +											Gesundheitsdiensteanbieterinnen /
 +											Gesundheitsdiensteanbieter berechnet und ermöglicht eine
 +											eindeutige Zuordnung der Gesundheitsdiensteanbieterin /
 +											des Gesundheitsdiensteanbieters im
 +										Gesundheitsbereich.</h6>
 +									</xsl:if>
 +									<xsl:if test="//saml:Attribute[@AttributeName='OID']">
 +										<h6>(***) OID: <i>Object Identifier</i> sind standardisierte
 +											Objekt-Bezeichner und beschreiben eindeutig die Rollen
 +											des GDA-Token Inhabers.</h6>
 +									</xsl:if>
 +								</body>
 +							</html>
 +						</xsl:template>
 +					</xsl:stylesheet>
 +				</dsig:Transform>
 +				<dsig:Transform
 +					Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"/>
 +			</dsig:Transforms>
 +			<sl:FinalDataMetaInfo>
 +				<sl:MimeType>text/html</sl:MimeType>
 +			</sl:FinalDataMetaInfo>
 +		</sl:TransformsInfo>
 +        <sl:TransformsInfo>
 +            <dsig:Transforms> <!-- xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"-->
 +                <dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116">
 +                    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#" exclude-result-prefixes="pr saml">
 +                        <xsl:output method="xml" xml:space="default"/>
 +                        <xsl:template match="/" xmlns="">
 +                            <text>
 +                                <xsl:text>Mit meiner elektronischen Signatur beantrage ich, </xsl:text>
 +                                <xsl:value-of select="//@Issuer"/>
 +                                <xsl:text>, geboren am </xsl:text>
 +                                <xsl:value-of select="substring(//saml:Attribute[@AttributeName='Geburtsdatum']/saml:AttributeValue,9,2)"/>
 +                                <xsl:text>.</xsl:text>
 +                                <xsl:value-of select="substring(//saml:Attribute[@AttributeName='Geburtsdatum']/saml:AttributeValue,6,2)"/>
 +                                <xsl:text>.</xsl:text>
 +                                <xsl:value-of select="substring(//saml:Attribute[@AttributeName='Geburtsdatum']/saml:AttributeValue,1,4)"/>
 +                                <xsl:text>, </xsl:text>
 +                                <xsl:if test="//saml:Attribute[@AttributeName='OIDTextualDescription']">
 +                                    <xsl:text>in der Rolle als </xsl:text>
 +                                    <xsl:value-of select="//saml:Attribute[@AttributeName='OIDTextualDescription']/saml:AttributeValue"/>
 +                                    <xsl:text>(OID***= </xsl:text>
 +                                    <xsl:value-of select="//saml:Attribute[@AttributeName='OID']/saml:AttributeValue"/>)
 +                                    <xsl:text>, </xsl:text>
 +                                </xsl:if>
 +                                <xsl:text>den Zugang zur gesicherten Anwendung.</xsl:text>
 +                                <xsl:text>

Datum und Uhrzeit: </xsl:text>
 +                                <xsl:value-of select="substring(//@IssueInstant,9,2)"/>
 +                                <xsl:text>.</xsl:text>
 +                                <xsl:value-of select="substring(//@IssueInstant,6,2)"/>
 +                                <xsl:text>.</xsl:text>
 +                                <xsl:value-of select="substring(//@IssueInstant,1,4)"/>
 +                                <xsl:text>, </xsl:text>
 +                                <xsl:value-of select="substring(//@IssueInstant,12,2)"/>
 +                                <xsl:text>:</xsl:text>
 +                                <xsl:value-of select="substring(//@IssueInstant,15,2)"/>
 +                                <xsl:text>:</xsl:text>
 +                                <xsl:value-of select="substring(//@IssueInstant,18,2)"/>
 +
 +                                <xsl:if test="//saml:Attribute[@AttributeName='HPI']">
 +                                    <xsl:text>

HPI(**): </xsl:text>
 +                                    <xsl:value-of select="//saml:Attribute[@AttributeName='HPI']/saml:AttributeValue"/>
 +                                </xsl:if>
 +
 +                                <xsl:if test="//saml:Attribute[@AttributeName='wbPK']">
 +                                    <xsl:text>

wbPK(*): </xsl:text>
 +                                    <xsl:value-of select="//saml:Attribute[@AttributeName='wbPK']/saml:AttributeValue/pr:Identification/pr:Value"/>
 +                                </xsl:if>
 +
 +                                <xsl:if test="//saml:Attribute[@AttributeName='MandatorName']">
 +                                    <xsl:text>

Ich bin weiters ermächtigt als </xsl:text>
 +                                    <xsl:value-of select="//saml:Attribute[@AttributeName='RepresentationType']/saml:AttributeValue/text()"/>
 +                                    <xsl:text>von </xsl:text>
 +                                    <xsl:value-of select="//saml:Attribute[@AttributeName='MandatorName']/saml:AttributeValue/text()"/>
 +                                    <xsl:if test="//saml:Attribute[@AttributeName='MandatorDateOfBirth']">
 +                                        <xsl:text>, geboren am </xsl:text>
 +                                        <xsl:value-of select="substring(//saml:Attribute[@AttributeName='MandatorDateOfBirth']/saml:AttributeValue,9,2)"/>
 +                                        <xsl:text>.</xsl:text>
 +                                        <xsl:value-of select="substring(//saml:Attribute[@AttributeName='MandatorDateOfBirth']/saml:AttributeValue,6,2)"/>
 +                                        <xsl:text>.</xsl:text>
 +                                        <xsl:value-of select="substring(//saml:Attribute[@AttributeName='MandatorDateOfBirth']/saml:AttributeValue,1,4)"/>
 +                                    </xsl:if>
 +                                    <xsl:if test="//saml:Attribute[@AttributeName='MandatorDomainIdentifier']">
 +                                        <xsl:text>,</xsl:text>
 +                                        <xsl:value-of select="//saml:Attribute[@AttributeName='MandatorDomainIdentifier']/saml:AttributeValue/text()"/>
 +                                    </xsl:if>
 +                                    <xsl:text>, in deren Auftrag zu handeln.</xsl:text>
 +
 +                                    <xsl:if test="//saml:Attribute[@AttributeName='MandatorWbpk']">
 +                                        <xsl:text>

wbPK(*) des Vollmachtgebers: </xsl:text>
 +                                        <xsl:value-of select="//saml:Attribute[@AttributeName='MandatorWbpk']/saml:AttributeValue/text()"/>
 +                                    </xsl:if>
 +                                </xsl:if>
 +
 +                                <xsl:if test="//saml:Attribute[@AttributeName='wbPK']">
 +                                    <xsl:text>

(*) wbPK: Das wirtschaftsbereichsspezifische Personenkennzeichen wird aus den jeweiligen Stammzahlen des Bürgers und des Wirtschaftsunternehmens berechnet und ermöglicht eine eindeutige Zuordnung des Bürgers zum Wirtschaftsunternehmen.</xsl:text>
 +                                </xsl:if>
 +                                <xsl:if test="//saml:Attribute[@AttributeName='HPI']">
 +                                    <xsl:text>

(**) HPI: Der eHealth Professional Identifier wird aus den jeweiligen Stammzahlen der Gesundheitsdiensteanbieterinnen / Gesundheitsdiensteanbieter berechnet und ermöglicht eine eindeutige Zuordnung der Gesundheitsdiensteanbieterin / des Gesundheitsdiensteanbieters im Gesundheitsbereich.</xsl:text>
 +                                </xsl:if>
 +                                <xsl:if test="//saml:Attribute[@AttributeName='OID']">
 +                                    <xsl:text>

(***) OID: Object Identifier sind standardisierte Objekt-Bezeichner und beschreiben eindeutig die Rollen des GDA-Token Inhabers.</xsl:text>
 +                                </xsl:if>
 +                            </text>
 +                        </xsl:template>
 +                    </xsl:stylesheet>
 +                </dsig:Transform>
 +                <dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
 +                    <dsig:XPath>not(text())</dsig:XPath>
 +                </dsig:Transform>
 +            </dsig:Transforms>
 +            <sl:FinalDataMetaInfo>
 +                <sl:MimeType>text/plain</sl:MimeType>
 +            </sl:FinalDataMetaInfo>
 +        </sl:TransformsInfo>
 +	</sl:DataObjectInfo>
 +	<sl:SignatureInfo>
 +		<sl:SignatureEnvironment>
 +			<sl:XMLContent>
 +				<saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion"
 +					xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#"
 +					MajorVersion="1" MinorVersion="0" AssertionID="any" Issuer="Klämens Örthäçké"
 +					IssueInstant="2008-06-05T11:26:10+02:00">
 +					<saml:AttributeStatement>
 +						<saml:Subject>
 +							<saml:NameIdentifier>https://demo.egiz.gv.at/exchange-moa-id-auth/</saml:NameIdentifier>
 +						</saml:Subject>
 +						<saml:Attribute AttributeName="wbPK"
 +							AttributeNamespace="http://reference.e-government.gv.at/namespace/moa/20020822#">
 +							<saml:AttributeValue>
 +								<pr:Identification>
 +									<pr:Value>LTpz8VYzns2jrx0J8Gm/R/nAhxA=</pr:Value>
 +									<pr:Type>urn:publicid:gv.at:wbpk+FN+TODO</pr:Type>
 +								</pr:Identification>
 +							</saml:AttributeValue>
 +						</saml:Attribute>
 +						<saml:Attribute AttributeName="OA"
 +							AttributeNamespace="http://reference.e-government.gv.at/namespace/moa/20020822#">
 +							<saml:AttributeValue>https://apps.egiz.gv.at/urlaubsschein-frontend/moaid-login</saml:AttributeValue>
 +						</saml:Attribute>
 +						<saml:Attribute AttributeName="Geburtsdatum"
 +							AttributeNamespace="http://reference.e-government.gv.at/namespace/moa/20020822#">
 +							<saml:AttributeValue>1971-11-10</saml:AttributeValue>
 +						</saml:Attribute>
 +					</saml:AttributeStatement>
 +				</saml:Assertion>
 +			</sl:XMLContent>
 +		</sl:SignatureEnvironment>
 +		<sl:SignatureLocation Index="2" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion">/saml:Assertion</sl:SignatureLocation>
 +	</sl:SignatureInfo>
 +</sl:CreateXMLSignatureRequest>
 diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java index 13c57686..86223854 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java @@ -30,8 +30,6 @@ package at.gv.egiz.smcc;  import java.nio.charset.Charset; -import java.util.logging.Level; -import java.util.logging.Logger;  import javax.smartcardio.CardChannel;  import javax.smartcardio.CardException;  import javax.smartcardio.CommandAPDU; @@ -41,7 +39,7 @@ import org.apache.commons.logging.Log;  import org.apache.commons.logging.LogFactory;  public class ACOSCard extends AbstractSignatureCard implements SignatureCard { -   +    private static Log log = LogFactory.getLog(ACOSCard.class);    public static final byte[] AID_DEC = new byte[] { (byte) 0xA0, (byte) 0x00, @@ -100,8 +98,15 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard {        (byte) 0x01 // RSA // TODO: Not verified yet    }; +  private static final int PINSPEC_INF = 0; +  private static final int PINSPEC_DEC = 1; +  private static final int PINSPEC_SIG = 2; +    public ACOSCard() {      super("at/gv/egiz/smcc/ACOSCard"); +    pinSpecs.add(PINSPEC_INF, new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("inf.pin.name"), KID_PIN_INF, null)); +    pinSpecs.add(PINSPEC_DEC, new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("dec.pin.name"), KID_PIN_DEC, null)); +    pinSpecs.add(PINSPEC_SIG, new PINSpec(6, 10, "[0-9]", getResourceBundle().getString("sig.pin.name"), KID_PIN_SIG, null));    }    /* (non-Javadoc) @@ -165,7 +170,8 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard {      try {        if ("IdentityLink".equals(infobox)) { -        PINSpec spec = new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("inf.pin.name")); +        PINSpec spec = pinSpecs.get(PINSPEC_INF); +        //new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("inf.pin.name"));          int retries = -1;          String pin = null; @@ -219,7 +225,8 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard {        if (KeyboxName.SECURE_SIGNATURE_KEYPAIR.equals(keyboxName)) { -        PINSpec spec = new PINSpec(6, 10, "[0-9]", getResourceBundle().getString("sig.pin.name")); +        PINSpec spec = pinSpecs.get(PINSPEC_SIG); +        //new PINSpec(6, 10, "[0-9]", getResourceBundle().getString("sig.pin.name"));          int retries = -1;          String pin = null; @@ -260,7 +267,8 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard {        } else if (KeyboxName.CERITIFIED_KEYPAIR.equals(keyboxName)) { -        PINSpec spec = new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("dec.pin.name")); +        PINSpec spec = pinSpecs.get(PINSPEC_DEC); +        //new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("dec.pin.name"));          int retries = -1;          String pin = null; @@ -322,11 +330,6 @@ public class ACOSCard extends AbstractSignatureCard implements SignatureCard {    }    @Override -  public byte[] getKIDs() { -    return new byte[] { KID_PIN_DEC, KID_PIN_INF, KID_PIN_SIG }; -  } - -  @Override    public int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException {      CardChannel channel = getCardChannel(); diff --git a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java index 67f090a5..cb068725 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/AbstractSignatureCard.java @@ -31,7 +31,11 @@ package at.gv.egiz.smcc;  import java.io.ByteArrayOutputStream;  import java.io.IOException;  import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List;  import java.util.Locale; +import java.util.Map;  import java.util.ResourceBundle;  import javax.smartcardio.ATR; @@ -49,6 +53,8 @@ public abstract class AbstractSignatureCard implements SignatureCard {    private static Log log = LogFactory.getLog(AbstractSignatureCard.class); +  protected List<PINSpec> pinSpecs = new ArrayList<PINSpec>(); +    private ResourceBundle i18n;    private String resourceBundleName; @@ -433,4 +439,8 @@ public abstract class AbstractSignatureCard implements SignatureCard {      }    } +  @Override +  public List<PINSpec> getPINSpecs() { +    return pinSpecs; +  }  } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/PINSpec.java b/smcc/src/main/java/at/gv/egiz/smcc/PINSpec.java index 0852d664..d180ddf0 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/PINSpec.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/PINSpec.java @@ -35,23 +35,40 @@ public class PINSpec {      String name_; +    byte kid_; + +    byte[] context_aid_; + +    /** +     * +     * @param minLenght +     * @param maxLength +     * @param rexepPattern +     * @param resourceBundle +     * @param name +     * @param kid the keyId for this pin +     */      public PINSpec(int minLenght, int maxLength, String rexepPattern,  -        ResourceBundle resourceBundle, String name) { +        ResourceBundle resourceBundle, String name, byte kid, byte[] contextAID) {          minLength_ = minLenght;          maxLength_ = maxLength;          rexepPattern_ = rexepPattern;          resourceBundle_ = resourceBundle;          name_ = name; +        kid_ = kid; +        context_aid_ = contextAID;      }      public PINSpec(int minLenght, int maxLength, String rexepPattern,  -        String name) { +        String name, byte kid, byte[] contextAID) {          minLength_ = minLenght;          maxLength_ = maxLength;          rexepPattern_ = rexepPattern;          name_ = name; +        kid_ = kid; +        context_aid_ = contextAID;      } @@ -75,7 +92,14 @@ public class PINSpec {      public String getRexepPattern() {          return rexepPattern_;      } -     + +    public byte getKID() { +      return kid_; +    } + +    public byte[] getContextAID() { +      return context_aid_; +    }  } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java index e80c6683..ae43629e 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java @@ -29,10 +29,8 @@  package at.gv.egiz.smcc;  import java.math.BigInteger; -import java.util.ArrayList;  import java.util.Arrays; -import java.util.List;  import javax.smartcardio.CardChannel;  import javax.smartcardio.CardException;  import javax.smartcardio.CommandAPDU; @@ -42,7 +40,7 @@ import org.apache.commons.logging.Log;  import org.apache.commons.logging.LogFactory;  public class STARCOSCard extends AbstractSignatureCard implements SignatureCard { -   +    /**     * Logging facility.     */ @@ -155,12 +153,17 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard    };    public static final byte KID_PIN_CARD = (byte) 0x01; -   + +  private static final int PINSPEC_CARD = 0; +  private static final int PINSPEC_SS = 1; +    /**     * Creates an new instance.     */    public STARCOSCard() {      super("at/gv/egiz/smcc/STARCOSCard"); +    pinSpecs.add(PINSPEC_CARD, new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("card.pin.name"), KID_PIN_CARD, null)); +    pinSpecs.add(PINSPEC_SS, new PINSpec(6, 10, "[0-9]", getResourceBundle().getString("sig.pin.name"), KID_PIN_SS, AID_DF_SS));    }    @Override @@ -210,7 +213,8 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard      try {        if ("IdentityLink".equals(infobox)) { -        PINSpec spec = new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("card.pin.name")); +        PINSpec spec = pinSpecs.get(PINSPEC_CARD); +        //new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("card.pin.name"));          int retries = -1;          String pin = null; @@ -302,7 +306,8 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard        if (KeyboxName.SECURE_SIGNATURE_KEYPAIR.equals(keyboxName)) { -        PINSpec spec = new PINSpec(6, 10, "[0-9]", getResourceBundle().getString("sig.pin.name")); +        PINSpec spec = pinSpecs.get(PINSPEC_SS); +        //new PINSpec(6, 10, "[0-9]", getResourceBundle().getString("sig.pin.name"));          int retries = -1;          String pin = null; @@ -334,7 +339,8 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard        } else if (KeyboxName.CERITIFIED_KEYPAIR.equals(keyboxName)) { -        PINSpec spec = new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("card.pin.name")); +        PINSpec spec = pinSpecs.get(PINSPEC_CARD); +        //new PINSpec(4, 4, "[0-9]", getResourceBundle().getString("card.pin.name"));          int retries = -1;          String pin = null; @@ -455,11 +461,6 @@ public class STARCOSCard extends AbstractSignatureCard implements SignatureCard      }    } -  @Override -  public byte[] getKIDs() { -    return new byte[] { KID_PIN_CARD, KID_PIN_SS }; -  } -    /**     * VERIFY PIN     * <p> diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java index bad7ccf6..8dc4ac2a 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java @@ -36,9 +36,13 @@ import java.security.cert.Certificate;  import java.security.cert.CertificateEncodingException;  import java.security.cert.CertificateException;  import java.security.cert.CertificateFactory; +import java.util.ArrayList;  import java.util.Enumeration; +import java.util.HashMap; +import java.util.List;  import java.util.Locale; +import java.util.Map;  import javax.smartcardio.Card;  import javax.smartcardio.CardTerminal; @@ -311,7 +315,7 @@ public class SWCard implements SignatureCard {      if (password == null) { -      PINSpec pinSpec = new PINSpec(0, -1, ".", "KeyStore-Password"); +      PINSpec pinSpec = new PINSpec(0, -1, ".", "KeyStore-Password", (byte) 0x01, null);        password = provider.providePIN(pinSpec, -1); @@ -390,13 +394,13 @@ public class SWCard implements SignatureCard {    }    @Override -  public byte[] getKIDs() { -    return null; +  public int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException { +    return -1;    }    @Override -  public int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException { -    return -1; +  public List<PINSpec> getPINSpecs() { +    return new ArrayList<PINSpec>();    }  } diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java index 1ec35b78..1e5e09c8 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java @@ -31,6 +31,7 @@ package at.gv.egiz.smcc;  import java.util.List;  import java.util.Locale; +import java.util.Map;  import javax.smartcardio.Card;  import javax.smartcardio.CardTerminal; @@ -118,10 +119,10 @@ public interface SignatureCard {        PINProvider provider) throws SignatureCardException, InterruptedException;    /** -   * get the KIDs for the availabel PINs +   * Get the KIDs for all available PINs and the corresponding PINSpecs     * @return array of KIDs     */ -  public byte[] getKIDs(); +  public List<PINSpec> getPINSpecs();    /**     * diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractBKUWorker.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractBKUWorker.java index e10ba8f9..b6c5a8ca 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractBKUWorker.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/AbstractBKUWorker.java @@ -102,6 +102,9 @@ public abstract class AbstractBKUWorker extends AbstractSMCCSTAL implements Acti    @Override    protected boolean waitForCard() { +    if (signatureCard != null) { +      return false; +    }      SMCCHelper smccHelper = new SMCCHelper();      actionCommandList.clear();      actionCommandList.add("cancel"); diff --git a/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java b/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java index a5f8a771..a5d6df23 100644 --- a/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java +++ b/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java @@ -86,15 +86,16 @@ public class AbstractSMCCSTALTest extends AbstractSMCCSTAL implements      }
 -      @Override
 -      public byte[] getKIDs() {
 -        return null;
 -      }
        @Override
        public int verifyPIN(String pin, byte kid) throws LockedException, NotActivatedException, SignatureCardException {
          return 0;
        }
 +
 +      @Override
 +      public List<PINSpec> getPINSpecs() {
 +        return new ArrayList<PINSpec>();
 +      }
     };
      return false;
 diff --git a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusProvider.java b/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefix.java index 73fa0920..c03f17cd 100644 --- a/BKUAppletExt/src/main/java/at/gv/egiz/bku/gui/PINStatusProvider.java +++ b/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefix.java @@ -15,18 +15,20 @@   * limitations under the License.   */ -package at.gv.egiz.bku.gui; - -import at.gv.egiz.smcc.SignatureCardException; +package at.gv.egiz.marshal;  /**   *   * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>   */ -public interface PINStatusProvider { - -  public enum STATUS { ACTIV, NOT_ACTIV, BLOCKED }; - -  public STATUS getPINStatus(int pin) throws SignatureCardException; +public interface NamespacePrefix { +  String CARDCHANNEL_PREFIX = "cc"; +  String ECDSA_PREFIX = "ecdsa"; +  String PERSONDATA_PREFIX = "pr"; +  String SAML10_PREFIX = "saml"; +  String SL_PREFIX = "sl"; +  String XADES_PREFIX = "xades"; +  String XMLDSIG_PREFIX = "xmldsig"; +  String XSI_PREFIX = "xsi";  } diff --git a/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefixMapperImpl.java b/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefixMapperImpl.java index a08c1188..519f6b1f 100644 --- a/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefixMapperImpl.java +++ b/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefixMapperImpl.java @@ -36,35 +36,35 @@ public class NamespacePrefixMapperImpl extends NamespacePrefixMapper {        log.trace("prefix for namespace " + namespaceUri + " requested");      }      if ("http://www.w3.org/2001/XMLSchema-instance".equals(namespaceUri)) { -      return "xsi"; +      return NamespacePrefix.XSI_PREFIX;      }      if ("http://www.w3.org/2000/09/xmldsig#".equals(namespaceUri)) { -      return "dsig"; +      return NamespacePrefix.XMLDSIG_PREFIX;      }      if ("http://www.buergerkarte.at/namespaces/securitylayer/1.2#".equals(namespaceUri)) { -      return "sl"; +      return NamespacePrefix.SL_PREFIX;      }      if ("http://www.buergerkarte.at/cardchannel".equals(namespaceUri)) { -      return "cc"; +      return NamespacePrefix.CARDCHANNEL_PREFIX;      }      if ("http://www.w3.org/2001/04/xmldsig-more#".equals(namespaceUri)) { -      return "ecdsa"; +      return NamespacePrefix.ECDSA_PREFIX;      }      if ("http://reference.e-government.gv.at/namespace/persondata/20020228#".equals(namespaceUri)) { -      return "pr"; +      return NamespacePrefix.PERSONDATA_PREFIX;      }      if ("urn:oasis:names:tc:SAML:1.0:assertion".equals(namespaceUri)) { -      return "saml"; +      return NamespacePrefix.SAML10_PREFIX;      }      if ("http://uri.etsi.org/01903/v1.1.1#".equals(namespaceUri)) { -      return "xades"; +      return NamespacePrefix.XADES_PREFIX;      }      return suggestion; diff --git a/utils/src/main/java/at/gv/egiz/slbinding/RedirectEventFilter.java b/utils/src/main/java/at/gv/egiz/slbinding/RedirectEventFilter.java index d2a7fb30..14c5ba48 100644 --- a/utils/src/main/java/at/gv/egiz/slbinding/RedirectEventFilter.java +++ b/utils/src/main/java/at/gv/egiz/slbinding/RedirectEventFilter.java @@ -1,19 +1,19 @@  /* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* Licensed 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. -*/ + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed 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. + */  /*   * To change this template, choose Tools | Templates   * and open the template in the editor. @@ -33,79 +33,84 @@ import javax.xml.stream.events.XMLEvent;  import org.apache.commons.logging.Log;  import org.apache.commons.logging.LogFactory; +/* + * TODO: don't set redirect stream from caller (caller does not know whether redirection will be triggered) + * rather create on trigger and pass to caller + */  public class RedirectEventFilter implements EventFilter { -    public static final String DEFAULT_ENCODING = "UTF-8"; -    private static Log log = LogFactory.getLog(RedirectEventFilter.class); -    protected XMLEventWriter redirectWriter = null; -    protected Set<QName> redirectTriggers = null; -    private int depth = -1; -    protected NamespaceContext currentNamespaceContext = null; +  public static final String DEFAULT_ENCODING = "UTF-8"; +  private static Log log = LogFactory.getLog(RedirectEventFilter.class); +  protected XMLEventWriter redirectWriter = null; +  protected Set<QName> redirectTriggers = null; +  private int depth = -1; +  protected NamespaceContext currentNamespaceContext = null; -    /** -     * Event redirection is disabled, set a redirect stream to enable. -     */ -    public RedirectEventFilter() { -        redirectWriter = null; -    // redirectTriggers = null; -    } +  /** +   * Event redirection is disabled, set a redirect stream to enable. +   */ +  public RedirectEventFilter() { +    redirectWriter = null; +  // redirectTriggers = null; +  } -    /** -     *  -     * @param redirectStream -     *          if null, no events are redirected -     * @param redirectTriggers -     *          if null, all events are redirected -     */ -    public RedirectEventFilter(OutputStream redirectStream, String encoding) -      throws XMLStreamException { // , List<QName> redirectTriggers -        if (redirectStream != null) { -            XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); -            if (encoding == null) { -                encoding = DEFAULT_ENCODING; -            } -            this.redirectWriter = outputFactory.createXMLEventWriter(redirectStream, +  /** +   * +   * @param redirectStream +   *          if null, no events are redirected +   * @param redirectTriggers +   *          if null, all events are redirected +   */ +  public RedirectEventFilter(OutputStream redirectStream, String encoding) +          throws XMLStreamException { // , List<QName> redirectTriggers +    if (redirectStream != null) { +      XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); +      if (encoding == null) { +        encoding = DEFAULT_ENCODING; +      } +      this.redirectWriter = outputFactory.createXMLEventWriter(redirectStream,                encoding); -        } -    // this.redirectTriggers = redirectTriggers;      } +  // this.redirectTriggers = redirectTriggers; +  } -    /** -     * All startElement events occuring in the redirectTriggers list will trigger -     * redirection of the entire (sub-)fragment. -     *  -     * @param event -     * @return false if an event is redirected -     */ -    @Override -    public boolean accept(XMLEvent event) { -        int eventType = event.getEventType(); +  /** +   * All startElement events occuring in the redirectTriggers list will trigger +   * redirection of the entire (sub-)fragment. +   * +   * @param event +   * @return false if an event is redirected +   */ +  @Override +  public boolean accept(XMLEvent event) { +    int eventType = event.getEventType(); -        if (eventType == XMLStreamConstants.START_ELEMENT) { -            currentNamespaceContext = event.asStartElement().getNamespaceContext(); -        } -        if (redirectWriter == null) { -            return true; -        } -        if (eventType == XMLStreamConstants.START_ELEMENT) { -            if (depth >= 0 || triggersRedirect(event.asStartElement().getName())) { -                depth++; -            } -        } else if (eventType == XMLStreamConstants.END_ELEMENT) { -            if (depth >= 0 && --depth < 0) { -                // redirect the end element of the trigger,  -                // but do not redirect the end element of the calling type -                if (redirectTriggers != null) { -                    redirectEvent(event); -                    return false; -                } -            } -        } -        if (depth >= 0) { //|| (depth == 0 && redirectTriggers == null)) { -            redirectEvent(event); -            return false; +    if (eventType == XMLStreamConstants.START_ELEMENT) { +      //hopefully, this is a copy +      currentNamespaceContext = event.asStartElement().getNamespaceContext(); +    } +    if (redirectWriter == null) { +      return true; +    } +    if (eventType == XMLStreamConstants.START_ELEMENT) { +      if (depth >= 0 || triggersRedirect(event.asStartElement().getName())) { +        depth++; +      } +    } else if (eventType == XMLStreamConstants.END_ELEMENT) { +      if (depth >= 0 && --depth < 0) { +        // redirect the end element of the trigger, +        // but do not redirect the end element of the calling type +        if (redirectTriggers != null) { +          redirectEvent(event); +          return false;          } -        return true; // depth < 0; +      } +    } +    if (depth >= 0) { //|| (depth == 0 && redirectTriggers == null)) { +      redirectEvent(event); +      return false; +    } +    return true; // depth < 0;  //    switch (event.getEventType()) {  //    case XMLStreamConstants.START_ELEMENT: @@ -132,128 +137,130 @@ public class RedirectEventFilter implements EventFilter {  //      return false;  //    }  //    return true; // depth < 0; -    } +  } -    /** -     * @param startElt -     * @return true if the set of triggers contains startElement  -     * (or no triggers are registered, i.e. everything is redirected) -     */ -    private boolean triggersRedirect(QName startElement) { -        if (redirectTriggers != null) { -            return redirectTriggers.contains(startElement); -        } -        return true; +  /** +   * @param startElt +   * @return true if the set of triggers contains startElement +   * (or no triggers are registered, i.e. everything is redirected) +   */ +  private boolean triggersRedirect(QName startElement) { +    if (redirectTriggers != null) { +      return redirectTriggers.contains(startElement);      } +    return true; +  } -    private void redirectEvent(XMLEvent event) { -        try { -            if (log.isTraceEnabled()) { -                log.trace("redirecting StAX event " + event); -            } -            redirectWriter.add(event); -        } catch (XMLStreamException ex) { -            ex.printStackTrace(); -        } +  private void redirectEvent(XMLEvent event) { +    try { +      if (log.isTraceEnabled()) { +        log.trace("redirecting StAX event " + event); +      } +      redirectWriter.add(event); +    } catch (XMLStreamException ex) { +      ex.printStackTrace();      } +  } -    /** -     * Enable/disable redirection of <em>all</em> events from now on.  -     * The redirected events will be UTF-8 encoded and written to the stream. -     *  -     * @param redirectstream -     *          if null, redirection is disabled -     */ -    public void setRedirectStream(OutputStream redirectStream) throws XMLStreamException { -        setRedirectStream(redirectStream, DEFAULT_ENCODING, null); -    } +  /** +   * Enable/disable redirection of <em>all</em> events from now on. +   * The redirected events will be UTF-8 encoded and written to the stream. +   * +   * @param redirectstream +   *          if null, redirection is disabled +   */ +  public void setRedirectStream(OutputStream redirectStream) throws XMLStreamException { +    setRedirectStream(redirectStream, DEFAULT_ENCODING, null); +  } -    /** -     * Enable/disable redirection of <em>all</em> events from now on.  -     *  -     * @param redirectStream if null, redirection is disabled -     * @param encoding The encoding for the redirect stream -     * @throws javax.xml.stream.XMLStreamException -     */ -    public void setRedirectStream(OutputStream redirectStream, String encoding) throws XMLStreamException { -        setRedirectStream(redirectStream, encoding, null); -    } +  /** +   * Enable/disable redirection of <em>all</em> events from now on. +   * +   * @param redirectStream if null, redirection is disabled +   * @param encoding The encoding for the redirect stream +   * @throws javax.xml.stream.XMLStreamException +   */ +  public void setRedirectStream(OutputStream redirectStream, String encoding) throws XMLStreamException { +    setRedirectStream(redirectStream, encoding, null); +  } -    /** -     * Enable/disable redirection of all (child) elements contained in redirect triggers. -     * The redirected events will be UTF-8 encoded and written to the stream. -     *  -     * @param redirectstream -     *          if null, redirection is disabled -     * @param redirectTriggers elements that trigger the redirection -     */ -    public void setRedirectStream(OutputStream redirectStream, Set<QName> redirectTriggers) throws XMLStreamException { -        setRedirectStream(redirectStream, DEFAULT_ENCODING, redirectTriggers); -    } +  /** +   * Enable/disable redirection of all (child) elements contained in redirect triggers. +   * The redirected events will be UTF-8 encoded and written to the stream. +   * +   * @param redirectstream +   *          if null, redirection is disabled +   * @param redirectTriggers elements that trigger the redirection +   */ +  public void setRedirectStream(OutputStream redirectStream, Set<QName> redirectTriggers) throws XMLStreamException { +    setRedirectStream(redirectStream, DEFAULT_ENCODING, redirectTriggers); +  } -    /** -     * Enable/disable redirection of all (child) elements contained in redirect triggers. -     *  -     * @param redirectstream -     *          if null, redirection is disabled -     * @param encoding The encoding for the redirect stream -     * @param redirectTriggers elements that trigger the redirection -     */ -    public void setRedirectStream(OutputStream redirectStream, String encoding, Set<QName> redirectTriggers) throws XMLStreamException { -        if (redirectStream != null) { -            XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); -            if (encoding == null) { -                encoding = DEFAULT_ENCODING; -            } -            redirectWriter = outputFactory.createXMLEventWriter(redirectStream, +  /** +   * Enable/disable redirection of all (child) elements contained in redirect triggers. +   * +   * TODO: don't set redirect stream from caller (caller does not know whether redirection will be triggered) +   * rather create on trigger and pass to caller +   * @param redirectstream +   *          if null, redirection is disabled +   * @param encoding The encoding for the redirect stream +   * @param redirectTriggers elements that trigger the redirection +   */ +  public void setRedirectStream(OutputStream redirectStream, String encoding, Set<QName> redirectTriggers) throws XMLStreamException { +    if (redirectStream != null) { +      XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); +      if (encoding == null) { +        encoding = DEFAULT_ENCODING; +      } +      redirectWriter = outputFactory.createXMLEventWriter(redirectStream,                encoding); -            if (redirectTriggers == null) { -                // start redirecting  -                depth = 0; -            } -            this.redirectTriggers = redirectTriggers; -        } else { -            redirectWriter = null; -            this.redirectTriggers = null; -        } +      if (redirectTriggers == null) { +        // start redirecting +        depth = 0; +      } +      this.redirectTriggers = redirectTriggers; +    } else { +      redirectWriter = null; +      this.redirectTriggers = null;      } +  } -    /** -     * Enable/disable redirection of fragments (defined by elements in -     * redirectTriggers) -     *  -     * @param redirectStream -     *          if null, redirection is disabled -     * @param redirectTriggers -     *          All startElement events occuring in this list will trigger -     *          redirection of the entire fragment. If null, all events are -     *          redirected -     */ -    // public void setRedirectStream(OutputStream redirectStream, List<QName> -    // redirectTriggers) throws XMLStreamException { -    // if (redirectStream != null) { -    // XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); -    // redirectWriter = outputFactory.createXMLEventWriter(redirectStream); -    // } else { -    // redirectWriter = null; -    // } -    // this.redirectTriggers = (redirectStream == null) ? null : redirectTriggers; -    // } -    /** -     * flushes the internal EventWriter -     *  -     * @throws javax.xml.stream.XMLStreamException -     */ -    public void flushRedirectStream() throws XMLStreamException { -        redirectWriter.flush(); -    } +  /** +   * Enable/disable redirection of fragments (defined by elements in +   * redirectTriggers) +   * +   * @param redirectStream +   *          if null, redirection is disabled +   * @param redirectTriggers +   *          All startElement events occuring in this list will trigger +   *          redirection of the entire fragment. If null, all events are +   *          redirected +   */ +  // public void setRedirectStream(OutputStream redirectStream, List<QName> +  // redirectTriggers) throws XMLStreamException { +  // if (redirectStream != null) { +  // XMLOutputFactory outputFactory = XMLOutputFactory.newInstance(); +  // redirectWriter = outputFactory.createXMLEventWriter(redirectStream); +  // } else { +  // redirectWriter = null; +  // } +  // this.redirectTriggers = (redirectStream == null) ? null : redirectTriggers; +  // } +  /** +   * flushes the internal EventWriter +   * +   * @throws javax.xml.stream.XMLStreamException +   */ +  public void flushRedirectStream() throws XMLStreamException { +    redirectWriter.flush(); +  } -    /** -     * the namespaceContext of the last startelement event read -     *  -     * @return -     */ -    public NamespaceContext getCurrentNamespaceContext() { -        return currentNamespaceContext; -    } +  /** +   * the namespaceContext of the last startelement event read +   * +   * @return +   */ +  public NamespaceContext getCurrentNamespaceContext() { +    return currentNamespaceContext; +  }  } diff --git a/utils/src/main/java/at/gv/egiz/slbinding/impl/TransformsInfoType.java b/utils/src/main/java/at/gv/egiz/slbinding/impl/TransformsInfoType.java index b4e988f0..1180e9fa 100644 --- a/utils/src/main/java/at/gv/egiz/slbinding/impl/TransformsInfoType.java +++ b/utils/src/main/java/at/gv/egiz/slbinding/impl/TransformsInfoType.java @@ -25,6 +25,7 @@ import java.io.ByteArrayOutputStream;  import java.util.HashSet;  import java.util.Set;  import javax.xml.bind.annotation.XmlTransient; +import javax.xml.namespace.NamespaceContext;  import javax.xml.namespace.QName;  import javax.xml.stream.XMLStreamException;  import org.apache.commons.logging.Log; diff --git a/utils/src/main/java/at/gv/egiz/slbinding/impl/XMLContentType.java b/utils/src/main/java/at/gv/egiz/slbinding/impl/XMLContentType.java index c32542aa..eb147f88 100644 --- a/utils/src/main/java/at/gv/egiz/slbinding/impl/XMLContentType.java +++ b/utils/src/main/java/at/gv/egiz/slbinding/impl/XMLContentType.java @@ -35,7 +35,7 @@ import org.apache.commons.logging.LogFactory;  public class XMLContentType extends at.buergerkarte.namespaces.securitylayer._1.XMLContentType implements RedirectCallback {      @XmlTransient -    private static Log log = LogFactory.getLog(TransformsInfoType.class); +    private static Log log = LogFactory.getLog(XMLContentType.class);      @XmlTransient      protected ByteArrayOutputStream redirectOS = null; diff --git a/utils/src/main/java/org/w3/_2000/_09/xmldsig_/ObjectFactory.java b/utils/src/main/java/org/w3/_2000/_09/xmldsig_/ObjectFactory.java index 4ab376f1..fae77451 100644 --- a/utils/src/main/java/org/w3/_2000/_09/xmldsig_/ObjectFactory.java +++ b/utils/src/main/java/org/w3/_2000/_09/xmldsig_/ObjectFactory.java @@ -167,6 +167,7 @@ public class ObjectFactory {       *        */      public TransformType createTransformType() { +//      return new at.gv.egiz.slbinding.impl.TransformType();          return new TransformType();      } diff --git a/utils/src/main/java/org/w3/_2000/_09/xmldsig_/TransformsType.java b/utils/src/main/java/org/w3/_2000/_09/xmldsig_/TransformsType.java index 584baf80..c7044c4c 100644 --- a/utils/src/main/java/org/w3/_2000/_09/xmldsig_/TransformsType.java +++ b/utils/src/main/java/org/w3/_2000/_09/xmldsig_/TransformsType.java @@ -57,7 +57,7 @@ import javax.xml.bind.annotation.XmlType;  })  public class TransformsType { -    @XmlElement(name = "Transform", required = true) +    @XmlElement(name = "Transform", required = true) //, type=at.gv.egiz.slbinding.impl.TransformType.class)      protected List<TransformType> transform;      /** diff --git a/utils/src/test/java/at/gv/egiz/slbinding/RedirectTest.java b/utils/src/test/java/at/gv/egiz/slbinding/RedirectTest.java index 99d353ac..7c8c206a 100644 --- a/utils/src/test/java/at/gv/egiz/slbinding/RedirectTest.java +++ b/utils/src/test/java/at/gv/egiz/slbinding/RedirectTest.java @@ -52,6 +52,8 @@ import javax.xml.stream.XMLEventReader;  import javax.xml.stream.XMLInputFactory;  import static org.junit.Assert.*; +import org.w3._2000._09.xmldsig_.TransformType; +import org.w3._2000._09.xmldsig_.TransformsType;  /**   * @@ -131,11 +133,34 @@ public class RedirectTest {                  Iterator<TransformsInfoType> tiIt = transformsInfos.iterator();                  while (tiIt.hasNext()) {                      at.gv.egiz.slbinding.impl.TransformsInfoType ti = (at.gv.egiz.slbinding.impl.TransformsInfoType) tiIt.next(); +//                    TransformsInfoType ti = tiIt.next();                      assertNotNull(ti); -                    System.out.println("found at.gv.egiz.slbinding.impl.TransformsInfoType TransformsInfo"); +                    System.out.println("found sl:TransformsInfo: " + ti.getClass().getName()); //at.gv.egiz.slbinding.impl.TransformsInfoType TransformsInfo"); +//                    TransformsType ts = ti.getTransforms(); +//                    assertNotNull(ts); +//                    System.out.println("found dsig:Transforms " + ts.getClass().getName()); //org.w3._2000._09.xmldsig_.TransformsType dsig:Transforms"); +//                    List<TransformType> tL = ts.getTransform(); +//                    assertNotNull(tL); +//                    System.out.println("found " + tL.size() + " org.w3._2000._09.xmldsig_.TransformType dsig:Transform"); +//                    for (TransformType t : tL) { +//                      if (t instanceof at.gv.egiz.slbinding.impl.TransformType) { +//                        System.out.println("found at.gv.egiz.slbinding.impl.TransformType"); +//                        byte[] redirectedBytes = ((at.gv.egiz.slbinding.impl.TransformType) t).getRedirectedStream().toByteArray(); +//                        if (redirectedBytes != null && redirectedBytes.length > 0) { +//                          System.out.println("reading redirected stream..."); +//                          os.write("--- redirected Transform ---".getBytes()); +//                          os.write(redirectedBytes); +//                          os.write("\n".getBytes()); +//                        } else { +//                          System.out.println("no redirected stream"); +//                        } +//                      } +//                    } +                      ByteArrayOutputStream dsigTransforms = ti.getRedirectedStream(); +                    os.write("--- redirected TransformsInfo content ---".getBytes());                      os.write(dsigTransforms.toByteArray()); -                    os.write("\n".getBytes()); +                    os.write("\n---".getBytes());                      MetaInfoType mi = ti.getFinalDataMetaInfo();                      assertNotNull(mi); diff --git a/utils/src/test/requests/CreateXMLSignatureRequest02.xml_redirect.txt b/utils/src/test/requests/CreateXMLSignatureRequest02.xml_redirect.txt index 31be50b7..fc0e4f14 100644 --- a/utils/src/test/requests/CreateXMLSignatureRequest02.xml_redirect.txt +++ b/utils/src/test/requests/CreateXMLSignatureRequest02.xml_redirect.txt @@ -1,4 +1,4 @@ -<dsig:Transforms> +--- redirected TransformsInfo content ---<dsig:Transforms>  				<dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></dsig:Transform>  				<dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116">  					<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#" version="1.0"> @@ -82,7 +82,7 @@  				</dsig:Transform>  				<dsig:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"></dsig:Transform>  			</dsig:Transforms> -<dsig:Transforms> +------ redirected TransformsInfo content ---<dsig:Transforms>  				<dsig:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></dsig:Transform>  				<dsig:Transform Algorithm="http://www.w3.org/TR/1999/REC-xslt-19991116">  					<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:saml="urn:oasis:names:tc:SAML:1.0:assertion" xmlns:pr="http://reference.e-government.gv.at/namespace/persondata/20020228#" version="1.0"> @@ -162,3 +162,4 @@  				</dsig:Transform>  				<dsig:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"></dsig:Transform>  			</dsig:Transforms> +---
\ No newline at end of file | 
