Java tutorial
/******************************************************************************* * Copyright (c) 2013 Dominik Schadow - http://www.xml-sicherheit.de All rights reserved. This program and the * accompanying materials are made available under the terms of the Eclipse Public License v1.0 which accompanies this * distribution, and is available at http://www.eclipse.org/legal/epl-v10.html * * Contributors: Dominik Schadow - initial API and implementation *******************************************************************************/ package org.jcryptool.crypto.xml.ui.sign; import java.io.File; import java.util.ArrayList; import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IAction; import org.eclipse.jface.action.MenuManager; import org.eclipse.jface.dialogs.IDialogSettings; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.viewers.CellEditor; import org.eclipse.jface.viewers.ColumnWeightData; import org.eclipse.jface.viewers.ICellModifier; import org.eclipse.jface.viewers.ILabelProviderListener; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.TableLayout; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.TextCellEditor; import org.eclipse.jface.wizard.WizardPage; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.VerifyEvent; import org.eclipse.swt.events.VerifyListener; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.FormAttachment; import org.eclipse.swt.layout.FormData; import org.eclipse.swt.layout.FormLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Event; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Listener; import org.eclipse.swt.widgets.Menu; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.TableItem; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.PlatformUI; import org.jcryptool.crypto.xml.core.sign.DigitalSignatureProperty; import org.jcryptool.crypto.xml.core.sign.Signature; import org.jcryptool.crypto.xml.core.utils.IAlgorithms; import org.jcryptool.crypto.xml.core.utils.IGlobals; import org.jcryptool.crypto.xml.core.utils.Utils; import org.jcryptool.crypto.xml.ui.utils.IContextHelpIds; /** * <p> * Last page of the wizard to create a XML signature. Lets the user select the <i>message digest algorithm</i>, the * <i>signature algorithm</i> and the <i>canonicalization</i> and <i>transformation algorithm</i>. Optional <i>Signature * Properties</i> can be provided. The <i>Signature ID</i> is optional but recommended. * </p> * * @author Dominik Schadow * @version 1.0.0 */ public class PageAlgorithms extends WizardPage implements Listener { /** Wizard page name. */ public static final String PAGE_NAME = "SignPageAlgorithms"; //$NON-NLS-1$ /** Message digest algorithms combo. */ private Combo cMDA = null; /** Signature algorithms combo. */ private Combo cSign = null; /** Canonicalization algorithms combo. */ private Combo cCanon = null; /** Transformation algorithms combo. */ private Combo cTransform = null; /** Signature ID text. */ private Text tId = null; /** Start Encryption Wizard afterwards checkbox. */ private Button bEncWiz = null; /** All signature IDs in the current XML document. */ private String[] ids; /** The signature properties table. */ private Table properties = null; /** The table viewer of the properties table. */ private TableViewer tableViewer = null; /** Property of the id column. */ private static final String ID_PROPERTY = "id"; /** Property of the target column. */ private static final String TARGET_PROPERTY = "target"; /** Property of the content column. */ private static final String CONTENT_PROPERTY = "content"; /** The button to add a new property row in the table. */ private Button bAddProperty = null; /** The button to remove a selected property row in the table. */ private Button bRemoveProperty = null; /** Stored setting for the Encryption Wizard call after signing. */ private static final String SETTING_CALL_ENCRYPTION_WIZARD = "sign_enc"; /** Model for the XML Signature Wizard. */ private Signature signature = null; /** * Constructor for PageAlgorithms. * * @param signature The signature wizard model */ public PageAlgorithms(final Signature signature) { super(PAGE_NAME); setTitle(Messages.signatureTitle); setDescription(Messages.algorithmsDescription); this.signature = signature; determineIds(); } /** * Creates the wizard page with the layout settings. * * @param parent Parent composite */ public void createControl(final Composite parent) { Composite container = new Composite(parent, SWT.NULL); FormLayout formLayout = new FormLayout(); container.setLayout(formLayout); createPageContent(container); addListeners(); setControl(container); loadSettings(); PlatformUI.getWorkbench().getHelpSystem().setHelp(getControl(), IContextHelpIds.WIZARD_SIGNATURE_ALGORITHMS); } /** * Fills this wizard page with content. Five groups (<i>Canonicalization and Transformation Algorithm</i>, * <i>Message Digest and Signature Algorithm</i>, <i>Signature Properties</i>, <i>Signature ID</i> and <i>Encryption * Wizard</i>) and all their widgets are inserted. * * @param parent Parent composite */ private void createPageContent(final Composite parent) { FormLayout layout = new FormLayout(); layout.marginTop = IGlobals.MARGIN / 2; layout.marginBottom = IGlobals.MARGIN / 2; layout.marginLeft = IGlobals.MARGIN / 2; layout.marginRight = IGlobals.MARGIN / 2; parent.setLayout(layout); // Five groups Group gTransform = new Group(parent, SWT.SHADOW_ETCHED_IN); gTransform.setLayout(layout); gTransform.setText(Messages.canonicalizationTransformation); FormData data = new FormData(); data.top = new FormAttachment(0, 0); data.left = new FormAttachment(0, 0); data.right = new FormAttachment(IGlobals.GROUP_NUMERATOR); gTransform.setLayoutData(data); Group gSign = new Group(parent, SWT.SHADOW_ETCHED_IN); gSign.setLayout(layout); gSign.setText(Messages.messageDigestSignature); data = new FormData(); data.top = new FormAttachment(gTransform, IGlobals.MARGIN, SWT.DEFAULT); data.left = new FormAttachment(0, 0); data.right = new FormAttachment(IGlobals.GROUP_NUMERATOR); gSign.setLayoutData(data); Group gProperties = new Group(parent, SWT.SHADOW_ETCHED_IN); gProperties.setLayout(layout); gProperties.setText(Messages.properties); data = new FormData(); data.top = new FormAttachment(gSign, IGlobals.MARGIN, SWT.DEFAULT); data.left = new FormAttachment(0, 0); data.right = new FormAttachment(IGlobals.GROUP_NUMERATOR); gProperties.setLayoutData(data); Group gID = new Group(parent, SWT.SHADOW_ETCHED_IN); gID.setLayout(layout); gID.setText(Messages.signatureId); data = new FormData(); data.top = new FormAttachment(gProperties, IGlobals.MARGIN, SWT.DEFAULT); data.left = new FormAttachment(0, 0); data.right = new FormAttachment(IGlobals.GROUP_NUMERATOR); gID.setLayoutData(data); Group gEncWiz = new Group(parent, SWT.SHADOW_ETCHED_IN); gEncWiz.setLayout(layout); gEncWiz.setText(Messages.encryptionWizard); data = new FormData(); data.top = new FormAttachment(gID, IGlobals.MARGIN * 2, SWT.DEFAULT); data.left = new FormAttachment(0, 0); data.right = new FormAttachment(IGlobals.GROUP_NUMERATOR); gEncWiz.setLayoutData(data); // Elements for group "Canonicalization and Transformation Algorithm" cCanon = new Combo(gTransform, SWT.READ_ONLY); data = new FormData(); data.left = new FormAttachment(gTransform); data.top = new FormAttachment(gTransform); data.width = IGlobals.COMBO_LARGE_WIDTH; cCanon.setLayoutData(data); cTransform = new Combo(gTransform, SWT.READ_ONLY); data = new FormData(); data.top = new FormAttachment(gTransform); data.left = new FormAttachment(cCanon, IGlobals.COMBO_MARGIN); data.width = IGlobals.COMBO_LARGE_WIDTH; cTransform.setLayoutData(data); // Elements for group "Message Digest and Signature Algorithm" cMDA = new Combo(gSign, SWT.READ_ONLY); data = new FormData(); data.width = IGlobals.COMBO_LARGE_WIDTH; data.top = new FormAttachment(gSign); data.left = new FormAttachment(gSign); cMDA.setLayoutData(data); cSign = new Combo(gSign, SWT.READ_ONLY); data = new FormData(); data.width = IGlobals.COMBO_LARGE_WIDTH; data.top = new FormAttachment(gSign); data.left = new FormAttachment(cMDA, IGlobals.COMBO_MARGIN); cSign.setLayoutData(data); // Elements for group "Signature Properties" properties = new Table(gProperties, SWT.FULL_SELECTION); properties.setHeaderVisible(true); properties.setLinesVisible(true); addProperties(); data = new FormData(); data.top = new FormAttachment(gProperties); data.left = new FormAttachment(gProperties); data.width = 350; data.height = 50; properties.setLayoutData(data); bAddProperty = new Button(gProperties, SWT.PUSH); bAddProperty.setText("+"); data = new FormData(); data.top = new FormAttachment(gProperties, 0, SWT.CENTER); data.left = new FormAttachment(properties, IGlobals.MARGIN); data.width = 50; bAddProperty.setLayoutData(data); bRemoveProperty = new Button(gProperties, SWT.PUSH); bRemoveProperty.setText("-"); data = new FormData(); data.top = new FormAttachment(gProperties, 25, SWT.CENTER); data.left = new FormAttachment(properties, IGlobals.MARGIN); data.width = 50; bRemoveProperty.setLayoutData(data); // Elements for group "Signature ID" Label lID = new Label(gID, SWT.SHADOW_IN); lID.setText(Messages.signatureId); data = new FormData(); data.top = new FormAttachment(gID); data.left = new FormAttachment(gID); data.width = 80; lID.setLayoutData(data); tId = new Text(gID, SWT.SINGLE); tId.setTextLimit(IGlobals.ID_LIMIT); data = new FormData(); data.top = new FormAttachment(gID); data.left = new FormAttachment(lID); data.width = IGlobals.MEDIUM_TEXT_WIDTH; tId.setLayoutData(data); // Elements for group "Encryption Wizard" bEncWiz = new Button(gEncWiz, SWT.CHECK); bEncWiz.setText(Messages.startEncryptionWizard); data = new FormData(); data.top = new FormAttachment(gEncWiz); data.left = new FormAttachment(gEncWiz); bEncWiz.setLayoutData(data); } /** * Sets the header of the properties table and adds the context menu to add and remove signature properties rows. */ private void addProperties() { tableViewer = new TableViewer(properties); TableLayout layout = new TableLayout(); layout.addColumnData(new ColumnWeightData(50, 50, true)); layout.addColumnData(new ColumnWeightData(125, 100, true)); layout.addColumnData(new ColumnWeightData(175, 150, true)); properties.setLayout(layout); TableColumn colId = new TableColumn(properties, SWT.LEFT); colId.setText(Messages.signaturePropertyId); colId.setToolTipText(Messages.signaturePropertyIdToolTip); TableColumn colTarget = new TableColumn(properties, SWT.LEFT); colTarget.setText(Messages.signaturePropertyTarget); colTarget.setToolTipText(Messages.signaturePropertyTargetToolTip); TableColumn colContent = new TableColumn(properties, SWT.LEFT); colContent.setText(Messages.signaturePropertyContent); colContent.setToolTipText(Messages.signaturePropertyContentToolTip); attachLabelProvider(tableViewer); attachCellEditors(tableViewer, properties); MenuManager popupMenu = new MenuManager(); IAction newRowAction = new NewRowAction(); IAction removeRowAction = new RemoveRowAction(); popupMenu.add(newRowAction); popupMenu.add(removeRowAction); Menu menu = popupMenu.createContextMenu(properties); properties.setMenu(menu); } /** * Adds the LabelProvider to the TableViewer. * * @param viewer The TableViewer */ private void attachLabelProvider(final TableViewer viewer) { viewer.setLabelProvider(new ITableLabelProvider() { public Image getColumnImage(final Object element, final int columnIndex) { return null; } public String getColumnText(final Object element, final int columnIndex) { if (element instanceof java.lang.String) { return (String) element; } switch (columnIndex) { case 0: return ((EditableTableItem) element).getId(); case 1: return ((EditableTableItem) element).getTarget(); case 2: return ((EditableTableItem) element).getContent(); default: return "Invalid column: " + columnIndex; } } public void addListener(final ILabelProviderListener listener) { } public void dispose() { } public boolean isLabelProperty(final Object element, final String property) { return false; } public void removeListener(final ILabelProviderListener listener) { } }); } /** * Adds the cell editors to the TableViewer. * * @param viewer The TableViewer * @param parent The parent composite */ private void attachCellEditors(final TableViewer viewer, final Composite parent) { viewer.setCellModifier(new ICellModifier() { public boolean canModify(final Object element, final String property) { return true; } public Object getValue(final Object element, final String property) { if (ID_PROPERTY.equals(property)) { return ((EditableTableItem) element).getId(); } else if (TARGET_PROPERTY.equals(property)) { return ((EditableTableItem) element).getTarget(); } else if (CONTENT_PROPERTY.equals(property)) { return ((EditableTableItem) element).getContent(); } else { return null; } } public void modify(final Object element, final String property, final Object value) { TableItem tableItem = (TableItem) element; EditableTableItem data = (EditableTableItem) tableItem.getData(); if (ID_PROPERTY.equals(property)) { data.setId(value.toString()); } else if (TARGET_PROPERTY.equals(property)) { data.setTarget(value.toString()); } else if (CONTENT_PROPERTY.equals(property)) { data.setContent(value.toString()); } viewer.refresh(data); } }); viewer.setCellEditors(new CellEditor[] { new TextCellEditor(parent), new TextCellEditor(parent), new TextCellEditor(parent) }); viewer.setColumnProperties(new String[] { ID_PROPERTY, TARGET_PROPERTY, CONTENT_PROPERTY }); } /** * Adds all listeners for the current wizard page. */ private void addListeners() { cMDA.addModifyListener(new ModifyListener() { public void modifyText(final ModifyEvent e) { dialogChanged(); } }); cSign.addModifyListener(new ModifyListener() { public void modifyText(final ModifyEvent e) { dialogChanged(); } }); cCanon.addModifyListener(new ModifyListener() { public void modifyText(final ModifyEvent e) { dialogChanged(); } }); cTransform.addModifyListener(new ModifyListener() { public void modifyText(final ModifyEvent e) { dialogChanged(); } }); tId.addVerifyListener(new VerifyListener() { public void verifyText(final VerifyEvent e) { if (e.keyCode == 8 || e.keyCode == 127) { e.doit = true; } else if (!Utils.validateId(e.text)) { e.doit = false; } } }); tId.addModifyListener(new ModifyListener() { public void modifyText(final ModifyEvent e) { dialogChanged(); } }); bAddProperty.addListener(SWT.Selection, this); bRemoveProperty.addListener(SWT.Selection, this); } /** * Determines all available signature ids in this XML document. */ private void determineIds() { ids = signature.getIds(); } /** * Determines the (error) message for the missing field. */ private void dialogChanged() { if (cCanon.getText().equals("")) { //$NON-NLS-1$ updateStatus(Messages.selectCanonicalization, IMessageProvider.INFORMATION); return; } else if (cTransform.getText().equals("")) { //$NON-NLS-1$ updateStatus(Messages.selectTransformation, IMessageProvider.INFORMATION); return; } else if (cMDA.getText().equals("")) { //$NON-NLS-1$ updateStatus(Messages.selectMessageDigest, IMessageProvider.INFORMATION); return; } else if (cSign.getText().equals("")) { //$NON-NLS-1$ updateStatus(Messages.selectSignature, IMessageProvider.INFORMATION); return; } if (!tId.getText().equals("")) { if (ids != null && ids.length > 0) { boolean uniqueId = Utils.ensureIdIsUnique(tId.getText(), ids); if (!uniqueId) { updateStatus(Messages.ambiguousSignatureId, IMessageProvider.ERROR); return; } } } updateStatus(null, IMessageProvider.NONE); } /** * Shows a message to the user to complete the fields on this page. * * @param message The message for the user * @param status The status type of the message */ private void updateStatus(final String message, final int status) { setMessage(message, status); if (message == null && getErrorMessage() == null) { setPageComplete(true); saveDataToModel(); } else { setPageComplete(false); } } /** * Called when finishing the wizard. * * @return Finishing status */ public boolean performFinish() { return saveDataToModel(); } /** * Handles the events from this wizard page. * * @param e The triggered event */ public void handleEvent(final Event e) { if (e.widget == bAddProperty) { // Button Add Property new NewRowAction().run(); } else if (e.widget == bRemoveProperty) { // Button Remove Property new RemoveRowAction().run(); } } /** * Sets the completed field on the wizard class when all the data is entered and the wizard can be completed. * * @return Page completion state */ public boolean isPageComplete() { saveDataToModel(); if (getMessage() == null && getErrorMessage() == null) { return true; } return false; } /** * Saves the selections on this wizard page to the model. Called on exit of the page. * * @return Saving state */ private boolean saveDataToModel() { signature.setMessageDigestAlgorithm(cMDA.getText()); signature.setSignatureAlgorithm(cSign.getText()); signature.setCanonicalizationAlgorithm(cCanon.getText()); signature.setTransformationAlgorithm(cTransform.getText()); if (properties.getItemCount() > 0) { ArrayList<DigitalSignatureProperty> signatureProperties = new ArrayList<DigitalSignatureProperty>(); for (int i = 0; i < properties.getItemCount(); i++) { TableItem tableItem = properties.getItem(i); EditableTableItem data = (EditableTableItem) tableItem.getData(); if (!"".equals(data.getId()) && !"".equals(data.getTarget())) { signatureProperties .add(new DigitalSignatureProperty(data.getId(), data.getTarget(), data.getContent())); } } signature.setSignatureProperties(signatureProperties); } signature.setSignatureId(tId.getText()); signature.setLaunchEncryptionWizard(bEncWiz.getSelection()); return true; } /** * Called on enter of the page to fill the combo boxes based on the selections on the first wizard page (like the * Basic Security Profile and detached file selections). Preselects a default value in every combo box. */ public void onEnterPage() { File detachedFile = signature.getDetachedFile(); String signatureType = signature.getSignatureType(); String fileType = null; if (detachedFile != null) { // Detached file String fileName = detachedFile.getName(); fileType = fileName.substring(fileName.lastIndexOf(".") + 1); //$NON-NLS-1$ } if (signature.getBsp()) { // BSP selected cCanon.setItems(IAlgorithms.CANONICALIZATION_ALGORITHMS_BSP); cCanon.setText(IAlgorithms.CANONICALIZATION_ALGORITHMS_BSP[0]); if (fileType == null || fileType.equalsIgnoreCase("xml")) { //$NON-NLS-1$ cTransform.setItems(IAlgorithms.TRANSFORMATION_ALGORITHMS_BSP); cTransform.select(0); } else { // arbitrary data, no transformation cTransform.setItems(IAlgorithms.NONE_ALGORITHM); cTransform.select(0); } cMDA.setItems(IAlgorithms.MD_ALGORITHMS_BSP); cMDA.select(0); cSign.setItems(IAlgorithms.SIGNATURE_ALGORITHMS_BSP); cSign.select(0); } else { // BSP not selected cCanon.setItems(IAlgorithms.CANONICALIZATION_ALGORITHMS); cCanon.select(0); // detached signature without XML file if (signatureType.equalsIgnoreCase("detached") && !fileType.equalsIgnoreCase("xml")) { cTransform.setItems(IAlgorithms.NONE_ALGORITHM); cTransform.select(0); } else { // enveloped or enveloping or detached signature with XML file cTransform.setItems(IAlgorithms.TRANSFORMATION_ALGORITHMS); cTransform.select(4); } cMDA.setItems(IAlgorithms.MD_ALGORITHMS); cMDA.setText(IAlgorithms.MD_ALGORITHMS[2]); cSign.setItems(IAlgorithms.SIGNATURE_ALGORITHMS); cSign.select(0); } setMessage(null); } /** * Loads the stored settings for this wizard page. */ private void loadSettings() { bEncWiz.setSelection(getDialogSettings().get(SETTING_CALL_ENCRYPTION_WIZARD) != null ? getDialogSettings().getBoolean(SETTING_CALL_ENCRYPTION_WIZARD) : false); } /** * Stores some settings of this wizard page in the current workspace. */ protected void storeSettings() { IDialogSettings settings = getDialogSettings(); settings.put(SETTING_CALL_ENCRYPTION_WIZARD, bEncWiz.getSelection()); } /** * Action to add a new property row. * * @author Dominik Schadow (info@xml-sicherheit.de), www.xml-sicherheit.de * @version 2.0.0, 28.01.2007 */ private class NewRowAction extends Action { /** * Constructor. */ public NewRowAction() { super(Messages.buttonAddProperty); } /** * Adds a new property row. */ public void run() { tableViewer.add(new EditableTableItem("", "", "")); } } /** * Action to remove a selected property row. * * @author Dominik Schadow (info@xml-sicherheit.de), www.xml-sicherheit.de * @version 2.0.0, 28.01.2007 */ private class RemoveRowAction extends Action { /** * Constructor. */ public RemoveRowAction() { super(Messages.buttonRemoveProperty); } /** * Removes the selected property row. */ public void run() { if (properties.getSelectionIndex() > -1) { properties.remove(properties.getSelectionIndex()); } } } }