org.eclipse.gyrex.admin.ui.http.jetty.internal.ImportCertificateDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.eclipse.gyrex.admin.ui.http.jetty.internal.ImportCertificateDialog.java

Source

/**
 * Copyright (c) 2011, 2012 Gunnar Wagenknecht and others.
 * 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:
 *     Gunnar Wagenknecht - initial API and implementation
 *     Andreas Mihm   - rework new admin ui
 */
package org.eclipse.gyrex.admin.ui.http.jetty.internal;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.Key;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.util.Enumeration;
import java.util.UUID;

import org.eclipse.gyrex.admin.ui.internal.application.AdminUiUtil;
import org.eclipse.gyrex.admin.ui.internal.widgets.Infobox;
import org.eclipse.gyrex.admin.ui.internal.widgets.NonBlockingStatusDialog;
import org.eclipse.gyrex.admin.ui.internal.wizards.dialogfields.DialogField;
import org.eclipse.gyrex.admin.ui.internal.wizards.dialogfields.IDialogFieldListener;
import org.eclipse.gyrex.admin.ui.internal.wizards.dialogfields.IUploadAdapter;
import org.eclipse.gyrex.admin.ui.internal.wizards.dialogfields.LayoutUtil;
import org.eclipse.gyrex.admin.ui.internal.wizards.dialogfields.SelectionButtonDialogFieldGroup;
import org.eclipse.gyrex.admin.ui.internal.wizards.dialogfields.Separator;
import org.eclipse.gyrex.admin.ui.internal.wizards.dialogfields.StringDialogField;
import org.eclipse.gyrex.admin.ui.internal.wizards.dialogfields.UploadDialogField;
import org.eclipse.gyrex.common.identifiers.IdHelper;
import org.eclipse.gyrex.http.jetty.admin.IJettyManager;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;

/**
 *
 */
public class ImportCertificateDialog extends NonBlockingStatusDialog {

    /** serialVersionUID */
    private static final long serialVersionUID = 1L;

    private static final String[] POSSIBLE_PKCS12_EXTENSIONS = new String[] { ".p12", ".pkcs12" };

    private final StringDialogField idField = new StringDialogField();
    private final StringDialogField keyStorePasswordField = new StringDialogField();
    private final StringDialogField keyPasswordField = new StringDialogField();
    private final SelectionButtonDialogFieldGroup keystoreTypeField = new SelectionButtonDialogFieldGroup(SWT.RADIO,
            new String[] { "JKS", "PKCS12" }, 2);
    private final UploadDialogField keystoreUploadField = new UploadDialogField();

    private Throwable importError;
    private String keystoreFileName;
    private byte[] keystoreBytes;
    private char[] generatedKeystorePassword;
    private char[] generatedKeyPassword;
    private final IJettyManager jettyManager;

    /**
     * Creates a new instance.
     * 
     * @param parent
     */
    public ImportCertificateDialog(final Shell parent, final IJettyManager jettyManager) {
        super(parent);
        this.jettyManager = jettyManager;
        setTitle("New Certificate");
        setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE | SWT.APPLICATION_MODAL);
    }

    @Override
    protected Control createDialogArea(final Composite parent) {
        final Composite composite = (Composite) super.createDialogArea(parent);
        final GridData gd = (GridData) composite.getLayoutData();
        gd.minimumHeight = convertVerticalDLUsToPixels(200);
        gd.minimumWidth = convertHorizontalDLUsToPixels(400);
        gd.widthHint = convertHorizontalDLUsToPixels(400);

        idField.setLabelText("Id");
        keystoreTypeField.setLabelText("Keystore Type");
        keyStorePasswordField.setLabelText("Keystore Password");
        keyPasswordField.setLabelText("Key Password");
        keystoreUploadField.setLabelText("Keystore");

        final IDialogFieldListener validateListener = new IDialogFieldListener() {
            @Override
            public void dialogFieldChanged(final DialogField field) {
                validate();
            }
        };

        idField.setDialogFieldListener(validateListener);
        keystoreTypeField.setDialogFieldListener(validateListener);
        keyStorePasswordField.setDialogFieldListener(validateListener);
        keyPasswordField.setDialogFieldListener(validateListener);
        keystoreUploadField.setDialogFieldListener(validateListener);

        final Infobox infobox = new Infobox(composite);
        infobox.setLayoutData(AdminUiUtil.createHorzFillData());
        infobox.addHeading("Import a keystore!");
        infobox.addParagraph(
                "Please fill in id, keytore type and passwords before uploading the keystore!\nAfter the upload the key store is validated. If the validation was sucessful,\nyou can import the key store into gyrex by pressing OK.");

        LayoutUtil.doDefaultLayout(composite, new DialogField[] { new Separator(), idField, new Separator(),
                keyStorePasswordField, keyPasswordField, new Separator(), keystoreTypeField, keystoreUploadField },
                false);
        LayoutUtil.setHorizontalGrabbing(idField.getTextControl(null));
        LayoutUtil.setHorizontalGrabbing(keystoreUploadField.getFileTextControl(null));

        final GridLayout masterLayout = (GridLayout) composite.getLayout();
        masterLayout.marginWidth = 5;
        masterLayout.marginHeight = 5;

        LayoutUtil.setHorizontalSpan(infobox, masterLayout.numColumns);

        return composite;
    }

    void importKeystore(final InputStream in) throws Exception {
        KeyStore tempKs;
        if (keystoreTypeField.isSelected(0)) {
            tempKs = KeyStore.getInstance("JKS");
        } else if (keystoreTypeField.isSelected(1)) {
            tempKs = KeyStore.getInstance("PKCS12");
        } else {
            throw new IllegalArgumentException(
                    "Please select a keystore type before uploading a keystore and retry.");
        }

        final String keystorePassword = keyStorePasswordField.getText();
        final String keyPassword = keyPasswordField.getText();

        // load keystore
        tempKs.load(new BufferedInputStream(in), null != keystorePassword ? keystorePassword.toCharArray() : null);

        // initialize new JKS store
        final KeyStore ks = KeyStore.getInstance("JKS");
        ks.load(null);

        generatedKeystorePassword = UUID.randomUUID().toString().toCharArray();
        generatedKeyPassword = UUID.randomUUID().toString().toCharArray();

        // verify and copy into new store
        final Enumeration aliases = tempKs.aliases();
        while (aliases.hasMoreElements()) {
            final String alias = (String) aliases.nextElement();
            if (tempKs.isKeyEntry(alias)) {
                final Key key = tempKs.getKey(alias, null != keyPassword ? keyPassword.toCharArray()
                        : null != keystorePassword ? keystorePassword.toCharArray() : null);
                Certificate[] chain = tempKs.getCertificateChain(alias);
                if (null == chain) {
                    final Certificate certificate = tempKs.getCertificate(alias);
                    if (null == certificate) {
                        // skip to next
                        continue;
                    }
                    chain = new Certificate[] { certificate };
                }
                ks.setKeyEntry("jetty", key, generatedKeyPassword, chain);
                break;
            }
        }

        if (!ks.aliases().hasMoreElements()) {
            throw new IllegalArgumentException(
                    "The uploaded keystore does not have a valid key + certificate chain entry. Please use a different keystore and retry.");
        }

        // write into bytes
        final ByteArrayOutputStream out = new ByteArrayOutputStream();
        ks.store(out, generatedKeystorePassword);

        keystoreBytes = out.toByteArray();
    }

    @Override
    protected void okPressed() {
        //      // activate background updates
        //      UICallBack.activate(getClass().getName() + "#" + Integer.toHexString(System.identityHashCode(this)));
        //
        // start and wait for update
        final Display display = getShell().getDisplay();
        final String fileName = keystoreUploadField.getFileName();
        if (StringUtils.isNotBlank(fileName) && (keystoreBytes == null || keystoreFileName == null
                || !StringUtils.equals(keystoreFileName, fileName))) {
            updateButtonsEnableState(
                    new Status(IStatus.ERROR, JettyConfigActivator.SYMBOLIC_NAME, "Upload in progress!")); // deactivate buttons
            keystoreUploadField.startUpload(new IUploadAdapter() {
                @Override
                public void receive(final InputStream stream, final String fileName, final String contentType,
                        final long contentLength) {
                    InputStream in = null;
                    try {
                        in = stream instanceof FileInputStream ? new BufferedInputStream(stream) : stream;
                        importKeystore(in);
                        keystoreFileName = fileName;
                        importError = null;
                    } catch (final Exception e) {
                        importError = e;
                        keystoreBytes = null;
                        keystoreFileName = null;
                        generatedKeyPassword = null;
                        generatedKeystorePassword = null;
                    } finally {
                        IOUtils.closeQuietly(in);
                    }
                    display.asyncExec(new Runnable() {
                        @Override
                        public void run() {
                            okPressedAndFileReceived();
                        }
                    });
                }
            });
        } else {
            // file is already uploaded
            okPressedAndFileReceived();
        }
    }

    void okPressedAndFileReceived() {
        // deactivate background updates
        //      UICallBack.deactivate(getClass().getName() + "#" + Integer.toHexString(System.identityHashCode(this)));

        if (importError != null) {
            setError("The uploaded keystore could not be imported.\n" + importError.getMessage());
            return;
        }

        validate();
        if (!getStatus().isOK()) {
            return;
        }

        try {
            jettyManager.addCertificate(idField.getText(), keystoreBytes, generatedKeystorePassword,
                    generatedKeyPassword);
        } catch (final Exception e) {
            setError(String.format("Error adding certificate: %s", e.getMessage()));
            return;
        }

        // close dialog
        super.okPressed();
    }

    private void setError(final String message) {
        updateStatus(new Status(IStatus.ERROR, JettyConfigActivator.SYMBOLIC_NAME, message));
        getShell().pack(true);
    }

    private void setInfo(final String message) {
        updateStatus(new Status(IStatus.INFO, JettyConfigActivator.SYMBOLIC_NAME, message));
    }

    private void setWarning(final String message) {
        updateStatus(new Status(IStatus.WARNING, JettyConfigActivator.SYMBOLIC_NAME, message));
    }

    void validate() {
        final String id = idField.getText();
        if (StringUtils.isNotBlank(id) && !IdHelper.isValidId(id)) {
            setError("The entered id is invalid. It may only contain ASCII chars a-z, 0-9, '.', '-' and/or '_'.");
            return;
        }

        if (StringUtils.isBlank(id)) {
            setInfo("Please enter a certificate id.");
            return;
        }

        if (!keystoreTypeField.isSelected(0) && !keystoreTypeField.isSelected(1)) {
            setInfo("Please select a keystore type.");
            return;
        }

        if (StringUtils.isBlank(keystoreUploadField.getFileName())) {
            setInfo("Please select a keystore to upload.");
            return;
        }

        if (StringUtils.endsWithAny(keystoreUploadField.getFileName().toLowerCase(), POSSIBLE_PKCS12_EXTENSIONS)
                && !keystoreTypeField.isSelected(1)) {
            setWarning(
                    "The selected file might be a PKCS12 keystore. Please verify the correct keystore type is selected!");
            return;
        }

        updateStatus(Status.OK_STATUS);
    }
}