org.jboss.tools.internal.deltacloud.ui.wizards.ManageKeysPage.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.tools.internal.deltacloud.ui.wizards.ManageKeysPage.java

Source

/*******************************************************************************
 * Copyright (c) 2010 Red Hat, Inc.
 * Distributed under license by Red Hat, Inc. All rights reserved.
 * This program is 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:
 *     Red Hat, Inc. - initial API and implementation
 ******************************************************************************/
package org.jboss.tools.internal.deltacloud.ui.wizards;

import java.io.File;
import java.text.MessageFormat;
import java.util.Arrays;

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateListStrategy;
import org.eclipse.core.databinding.UpdateSetStrategy;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.beans.BeanProperties;
import org.eclipse.core.databinding.conversion.Converter;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jface.layout.GridDataFactory;
import org.eclipse.jface.layout.GridLayoutFactory;
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.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.FormLayout;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.jboss.tools.common.log.StatusFactory;
import org.jboss.tools.common.ui.WizardUtils;
import org.jboss.tools.common.ui.ssh.SshPrivateKeysPreferences;
import org.jboss.tools.deltacloud.core.DeltaCloud;
import org.jboss.tools.deltacloud.core.DeltaCloudException;
import org.jboss.tools.deltacloud.core.DeltaCloudKey;
import org.jboss.tools.deltacloud.core.job.AbstractCloudElementJob;
import org.jboss.tools.deltacloud.core.job.AbstractCloudElementJob.CLOUDELEMENT;
import org.jboss.tools.deltacloud.ui.Activator;
import org.jboss.tools.deltacloud.ui.ErrorUtils;
import org.jboss.tools.deltacloud.ui.SWTImagesFactory;
import org.jboss.tools.internal.deltacloud.ui.common.databinding.validator.ObjectNotNullToBoolean;
import org.jboss.tools.internal.deltacloud.ui.utils.LayoutUtils;

/**
 * @author Jeff Johnston
 * @author Andr Dietisheim
 */
public class ManageKeysPage extends WizardPage {

    private final static String NAME = "ManageKeys.name"; //$NON-NLS-1$
    private final static String TITLE = "ManageKeys.title"; //$NON-NLS-1$
    private final static String DESC = "ManageKeys.desc"; //$NON-NLS-1$
    private final static String NEW = "NewButton.label"; //$NON-NLS-1$
    private final static String DELETE = "DeleteButton.label"; //$NON-NLS-1$
    private final static String CREATE_KEY_TITLE = "CreateKey.title"; //$NON-NLS-1$
    private final static String CONFIRM_KEY_DELETE_TITLE = "ConfirmKeyDelete.title"; //$NON-NLS-1$
    private final static String CONFIRM_KEY_DELETE_MSG = "ConfirmKeyDelete.msg"; //$NON-NLS-1$

    private ManageKeysPageModel model;
    private DataBindingContext dbc;

    private class Key2IdConverter extends Converter {

        public Key2IdConverter() {
            super(Object.class, String.class);
        }

        @Override
        public Object convert(Object fromObject) {
            if (fromObject == null) {
                return null;
            }
            Assert.isTrue(fromObject instanceof DeltaCloudKey);
            return ((DeltaCloudKey) fromObject).getId();
        }

    }

    private class Id2KeyConverter extends Converter {

        public Id2KeyConverter() {
            super(String.class, DeltaCloudKey.class);
        }

        @Override
        public Object convert(Object fromObject) {
            if (fromObject == null) {
                return null;
            }
            Assert.isTrue(fromObject instanceof String);
            return model.getKey((String) fromObject);
        }
    }

    public ManageKeysPage(DeltaCloud cloud) {
        super(WizardMessages.getString(NAME));
        this.model = new ManageKeysPageModel(cloud);
        setDescription(WizardMessages.getString(DESC));
        setTitle(WizardMessages.getString(TITLE));
        setImageDescriptor(SWTImagesFactory.DESC_DELTA_LARGE);
        setPageComplete(false);
    }

    @Override
    public void createControl(Composite parent) {
        this.dbc = new DataBindingContext();
        // WizardPageSupport.create(this, dbc);
        bindWizardComplete(dbc);

        Composite container = new Composite(parent, SWT.NULL);
        GridLayoutFactory.fillDefaults().numColumns(4).equalWidth(false).applyTo(container);

        Label keyListLabel = new Label(container, SWT.NULL);
        keyListLabel.setText("Keys available on the server:");
        GridDataFactory.fillDefaults().span(4, 1).applyTo(keyListLabel);

        List keyList = createKeyList(dbc, container);
        GridDataFactory.fillDefaults().align(SWT.FILL, SWT.FILL).grab(true, true).span(4, 8).hint(100, 200)
                .applyTo(keyList);

        Button refreshButton = new Button(container, SWT.NULL);
        refreshButton.setText("Refresh keys");
        refreshButton.addSelectionListener(onRefreshPressed());
        GridDataFactory.fillDefaults().applyTo(refreshButton);

        Label dummyLabel = new Label(container, SWT.NULL);
        GridDataFactory.fillDefaults().grab(true, false).applyTo(dummyLabel);

        Button createButton = createNewButton(container, dbc);
        GridDataFactory.fillDefaults().applyTo(createButton);

        Button deleteButton = createDeleteButton(container, dbc);
        GridDataFactory.fillDefaults().applyTo(deleteButton);

        setControl(container);
        refreshKeys();
    }

    private Button createNewButton(Composite container, DataBindingContext dbc) {
        Button newButton = new Button(container, SWT.NULL);
        newButton.setText(WizardMessages.getString(NEW));
        newButton.addSelectionListener(onNewPressed());
        return newButton;
    }

    private Button createDeleteButton(Composite container, DataBindingContext dbc) {
        Button deleteButton = new Button(container, SWT.NULL);
        deleteButton.setText(WizardMessages.getString(DELETE));
        deleteButton.addSelectionListener(onDeletePressed());
        // bind enablement
        dbc.bindValue(WidgetProperties.enabled().observe(deleteButton),
                BeanProperties.value(ManageKeysPageModel.PROP_SELECTED_KEY).observe(model),
                new UpdateValueStrategy(UpdateSetStrategy.POLICY_NEVER),
                new UpdateValueStrategy().setConverter(new ObjectNotNullToBoolean()));
        return deleteButton;
    }

    private void bindWizardComplete(DataBindingContext dbc) {
        dbc.bindValue(BeanProperties.value("pageComplete").observe(this),
                BeanProperties.value(ManageKeysPageModel.PROP_SELECTED_KEY).observe(model),
                new UpdateValueStrategy(UpdateSetStrategy.POLICY_NEVER),
                new UpdateValueStrategy().setConverter(new ObjectNotNullToBoolean()));
    }

    @Override
    public void setPageComplete(boolean complete) {
        super.setPageComplete(complete);
    }

    private List createKeyList(DataBindingContext dbc, Composite container) {
        final List keyList = new List(container, SWT.BORDER | SWT.SINGLE | SWT.V_SCROLL);
        // bind items
        dbc.bindList(WidgetProperties.items().observe(keyList),
                BeanProperties.list(ManageKeysPageModel.PROP_KEYS).observe(model),
                new UpdateListStrategy(UpdateSetStrategy.POLICY_NEVER),
                new UpdateListStrategy().setConverter(new Key2IdConverter()));
        // bind selected key
        dbc.bindValue(WidgetProperties.selection().observe(keyList),
                BeanProperties.value(ManageKeysPageModel.PROP_SELECTED_KEY).observe(model),
                new UpdateValueStrategy().setConverter(new Id2KeyConverter()),
                new UpdateValueStrategy().setConverter(new Key2IdConverter()));

        keyList.addListener(SWT.MouseDoubleClick, onKeyDoubleclick());

        return keyList;
    }

    private SelectionAdapter onDeletePressed() {
        return new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent event) {
                DeltaCloudKey key = model.getSelectedKey();
                boolean confirmed = MessageDialog.openConfirm(getShell(),
                        WizardMessages.getString(CONFIRM_KEY_DELETE_TITLE),
                        WizardMessages.getFormattedString(CONFIRM_KEY_DELETE_MSG, key.getId()));
                if (confirmed) {
                    deleteSelectedKey();
                }
            }
        };
    }

    private SelectionListener onRefreshPressed() {
        return new SelectionAdapter() {

            @Override
            public void widgetSelected(SelectionEvent e) {
                refreshKeys();
            }
        };
    }

    private Listener onKeyDoubleclick() {
        return new Listener() {

            @Override
            public void handleEvent(Event event) {
                WizardUtils.nextPageOrFinish(ManageKeysPage.this);
            }
        };
    }

    private void refreshKeys() {
        Job job = new AbstractCloudElementJob("Get keys", model.getCloud(), CLOUDELEMENT.KEYS) {

            protected IStatus doRun(IProgressMonitor monitor) throws Exception {
                try {
                    model.refreshKeys();
                    return Status.OK_STATUS;
                } catch (DeltaCloudException e) {
                    return StatusFactory.getInstance(IStatus.ERROR, Activator.PLUGIN_ID,
                            MessageFormat.format("Could not get keys from cloud {0}", getCloud().getName()), e);
                }
            }
        };
        try {
            WizardUtils.runInWizard(job, getContainer(), dbc);
        } catch (Exception e) {
            // ignore since the job will report its failure
        }
    }

    private SelectionListener onNewPressed() {
        return new SelectionAdapter() {
            public void widgetSelected(SelectionEvent event) {
                java.util.List<DeltaCloudKey> keys = model.getKeys();
                String[] keys2 = new String[keys.size()];
                for (int i = 0; i < keys2.length; i++) {
                    keys2[i] = keys.get(i).getId();
                }
                AddKeyDialog dialog = new AddKeyDialog(getShell(), keys2);
                if (dialog.open() == Dialog.OK) {
                    String keyId = dialog.getKeyId();
                    DeltaCloudKey key = createKey(keyId);
                    if (dialog.shouldPersist()) {
                        storeKeyLocally(key, dialog.getFolder());
                    }
                }
            }
        };
    }

    private class AddKeyDialog extends TitleAreaDialog {
        private String[] existingKeys;
        private Text pemText, nameText;
        private Button persist;
        private String pem, name;
        private boolean persistBool;

        public AddKeyDialog(Shell parentShell, String[] existingKeys) {
            super(parentShell);
            this.existingKeys = existingKeys;
        }

        protected Control createDialogArea(Composite parent) {
            // create the top level composite for the dialog area
            Composite composite = new Composite(parent, SWT.NONE);
            composite.setLayoutData(new GridData(GridData.FILL_BOTH));
            composite.setFont(parent.getFont());
            composite.setLayout(new FormLayout());
            Label titleBarSeparator = new Label(composite, SWT.HORIZONTAL | SWT.SEPARATOR);
            titleBarSeparator.setLayoutData(LayoutUtils.createFormData(0, 0, null, 0, 0, 0, 100, 0));

            setTitle(WizardMessages.getString(CREATE_KEY_TITLE));
            Label nameLabel = new Label(composite, SWT.NONE);
            nameLabel.setText("Key ID: ");
            nameLabel.setLayoutData(LayoutUtils.createFormData(0, 7, null, 0, 0, 5, null, 0));
            nameText = new Text(composite, SWT.BORDER);
            nameText.setLayoutData(LayoutUtils.createFormData(0, 5, null, 0, nameLabel, 5, 100, -5));

            persist = new Button(composite, SWT.CHECK);
            persist.setText("Save key in folder: ");
            persist.setLayoutData(LayoutUtils.createFormData(nameText, 8, null, 0, 0, 5, null, 0));

            Button browse = new Button(composite, SWT.DEFAULT);
            browse.setText("Browse...");
            browse.setLayoutData(LayoutUtils.createFormData(nameText, 5, null, 0, null, 0, 100, -5));
            browse.addSelectionListener(new SelectionAdapter() {
                public void widgetSelected(SelectionEvent e) {
                    DirectoryDialog dialog = new DirectoryDialog(getShell(), SWT.NONE);
                    dialog.setFilterPath(model.getKeyStorePath());
                    dialog.setText("Choose a directory to store new keys");
                    String keyStorePath = dialog.open();
                    pemText.setText(keyStorePath);
                }
            });

            pemText = new Text(composite, SWT.BORDER);
            pemText.setLayoutData(LayoutUtils.createFormData(nameText, 5, null, 0, persist, 5, browse, -5));

            init();

            ModifyListener listener = new ModifyListener() {
                public void modifyText(ModifyEvent e) {
                    verify();
                }
            };

            nameText.addModifyListener(listener);
            pemText.addModifyListener(listener);
            persist.addSelectionListener(new SelectionAdapter() {
                public void widgetSelected(SelectionEvent e) {
                    verify();
                }
            });

            return composite;
        }

        private void init() {
            persist.setSelection(true);
            pemText.setText(model.getInitialKeyStorePath());
            verify();
        }

        private void verify() {
            persistBool = persist.getSelection();
            pem = pemText.getText();
            name = nameText.getText();
            File pemFolder = new File(pem);
            if (!pemFolder.exists()) {
                setErrorMessage("Key folder does not exist.");
            } else if (!pemFolder.canWrite()) {
                setErrorMessage("Key folder is not writable.");
            } else if (Arrays.asList(existingKeys).contains(name)) {
                setErrorMessage("Key id is already used, please choose another id.");
            } else {
                setErrorMessage(null);
            }
        }

        public String getKeyId() {
            return name;
        }

        public String getFolder() {
            return pem;
        }

        public boolean shouldPersist() {
            return persistBool;
        }
    }

    private DeltaCloudKey createKey(final String keyId) {
        final DeltaCloudKey[] keyHolder = new DeltaCloudKey[1];
        try {
            Job job = new AbstractCloudElementJob("Create new key", model.getCloud(), CLOUDELEMENT.KEYS) {

                protected IStatus doRun(IProgressMonitor monitor) throws Exception {
                    try {
                        keyHolder[0] = model.createKey(keyId);
                        return Status.OK_STATUS;
                    } catch (DeltaCloudException e) {
                        return StatusFactory.getInstance(IStatus.ERROR, Activator.PLUGIN_ID,
                                MessageFormat.format("Could not create key \"{0}\"", keyId), e);
                    }
                }
            };
            WizardUtils.runInWizard(job, getContainer(), dbc);
        } catch (Exception e) {
            // ignore
        }
        return keyHolder[0];
    }

    private void storeKeyLocally(DeltaCloudKey key, String pemFolder) {
        try {
            if (key != null) {
                model.storeKeyLocally(key, pemFolder);
            }
        } catch (Exception e) {
            ErrorUtils.handleError("Error",
                    MessageFormat.format("Could not store key \"{0}\" locally and add it to the ssh private keys",
                            key.getName()),
                    e, getShell());
        }
    }

    private void deleteSelectedKey() {
        try {
            Job job = new AbstractCloudElementJob(
                    MessageFormat.format("Delete key {0}", model.getSelectedKey().getName()), model.getCloud(),
                    CLOUDELEMENT.KEYS) {

                protected IStatus doRun(IProgressMonitor monitor) throws Exception {
                    try {
                        final DeltaCloudKey key = model.deleteSelectedKey();
                        final boolean[] isConfirmDelete = new boolean[] { false };
                        if (PemFileManager.exists(key.getName(), SshPrivateKeysPreferences.getSshKeyDirectory())) {
                            getShell().getDisplay().syncExec(new Runnable() {

                                @Override
                                public void run() {
                                    isConfirmDelete[0] = MessageDialog.openConfirm(getShell(),
                                            MessageFormat.format("Delete key {0} locally?", key.getName()),
                                            MessageFormat.format(
                                                    "Shall the key \"{0}\" be deleted from local key store?",
                                                    key.getName()));
                                }
                            });
                            if (isConfirmDelete[0]) {
                                model.removeKeyLocally(key);
                            }
                        }
                        return Status.OK_STATUS;
                    } catch (DeltaCloudException e) {
                        return StatusFactory.getInstance(IStatus.ERROR, Activator.PLUGIN_ID,
                                MessageFormat.format("Could not delete key", model.getSelectedKey().getId()), e);
                    }
                }
            };
            WizardUtils.runInWizard(job, getContainer(), dbc);
            //         // WORKAROUND (wizard runnable service always reenables OK-button)
            //         setPageComplete(isPageComplete());
        } catch (Exception e) {
            // ignore
        }
    }

    public DeltaCloudKey getKey() {
        return model.getSelectedKey();
    }
}