org.eurocarbdb.application.glycoworkbench.plugin.s3.gui.StartupDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.eurocarbdb.application.glycoworkbench.plugin.s3.gui.StartupDialog.java

Source

/*
 * jets3t : Java Extra-Tasty S3 Toolkit (for Amazon S3 online storage service)
 * This is a java.net project, see https://jets3t.dev.java.net/
 *
 * Copyright 2006 James Murty, 2008 Zmanda Inc.
 *
 * 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 org.eurocarbdb.application.glycoworkbench.plugin.s3.gui;

import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTabbedPane;
import javax.swing.KeyStroke;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jets3t.gui.ErrorDialog;
import org.jets3t.gui.HyperlinkActivatedListener;
import org.jets3t.gui.ProgressDialog;
import org.jets3t.service.Constants;
import org.jets3t.service.Jets3tProperties;
import org.jets3t.service.S3Service;
import org.jets3t.service.S3ServiceException;
import org.jets3t.service.acl.AccessControlList;
import org.jets3t.service.impl.rest.httpclient.RestS3Service;
import org.jets3t.service.model.S3Bucket;
import org.jets3t.service.model.S3Object;
import org.jets3t.service.security.AWSCredentials;
import org.jets3t.service.security.AWSDevPayCredentials;
import org.jets3t.service.utils.ServiceUtils;

import com.centerkey.utils.BareBonesBrowserLaunch;

/**
 * Dialog box for obtaining a user's AWS Credentials, and performing other startup tasks such as
 * loading properties files.
 * <p>
 *
 * @author James Murty
 * @author Nikolas Coukouma
 */
public class StartupDialog extends JDialog implements ActionListener, ChangeListener {
    private static final long serialVersionUID = -2520889480615456474L;

    private static final Log log = LogFactory.getLog(StartupDialog.class);

    public static final String EMPTY_PASSWORD_SURROGATE = "NONE";

    private Frame ownerFrame = null;
    private HyperlinkActivatedListener hyperlinkListener = null;
    private Jets3tProperties myProperties = null;

    private AWSCredentials awsCredentials = null;

    private JButton okButton = null;
    private JButton cancelButton = null;
    private JButton storeCredentialsButton = null;
    private JTabbedPane tabbedPane = null;
    private LoginPassphrasePanel loginPassphrasePanel = null;
    private LoginLocalFolderPanel loginLocalFolderPanel = null;
    private LoginCredentialsPanel loginCredentialsPanel = null;

    private final Insets insetsZero = new Insets(0, 0, 0, 0);
    private final Insets insetsDefault = new Insets(3, 5, 3, 5);

    private static final int LOGIN_MODE_PASSPHRASE = 0;
    private static final int LOGIN_MODE_LOCAL_FOLDER = 1;
    private static final int LOGIN_MODE_DIRECT = 2;
    private int loginMode = LOGIN_MODE_PASSPHRASE;

    /**
     * Creates a modal dialog box with a title.
     *
     * @param owner
     * the frame within which this dialog will be displayed and centred.
     * @param hyperlinkListener
     */
    public StartupDialog(Frame owner, Jets3tProperties properties, HyperlinkActivatedListener hyperlinkListener) {
        super(owner, "Cockpit Login", true);
        this.ownerFrame = owner;
        this.hyperlinkListener = hyperlinkListener;
        this.myProperties = properties;
        this.initGui();
    }

    /**
     * Initialises all GUI elements.
     */
    private void initGui() {
        this.setResizable(false);
        this.setDefaultCloseOperation(JDialog.HIDE_ON_CLOSE);

        cancelButton = new JButton("Don't log in");
        cancelButton.setActionCommand("Cancel");
        cancelButton.addActionListener(this);
        storeCredentialsButton = new JButton("Store Credentials");
        storeCredentialsButton.setActionCommand("StoreCredentials");
        storeCredentialsButton.addActionListener(this);
        okButton = new JButton("Log in");
        okButton.setActionCommand("LogIn");
        okButton.addActionListener(this);

        // Set default ENTER and ESCAPE buttons.
        this.getRootPane().setDefaultButton(okButton);
        this.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("ESCAPE"),
                "ESCAPE");
        this.getRootPane().getActionMap().put("ESCAPE", new AbstractAction() {
            private static final long serialVersionUID = -1742280851624947873L;

            public void actionPerformed(ActionEvent actionEvent) {
                setVisible(false);
            }
        });

        JPanel buttonsPanel = new JPanel(new GridBagLayout());
        buttonsPanel.add(cancelButton, new GridBagConstraints(0, 0, 1, 1, 1, 0, GridBagConstraints.WEST,
                GridBagConstraints.NONE, insetsZero, 0, 0));
        buttonsPanel.add(storeCredentialsButton, new GridBagConstraints(1, 0, 1, 1, 1, 0, GridBagConstraints.EAST,
                GridBagConstraints.NONE, insetsZero, 0, 0));
        buttonsPanel.add(okButton, new GridBagConstraints(2, 0, 1, 1, 0, 0, GridBagConstraints.EAST,
                GridBagConstraints.NONE, insetsZero, 0, 0));

        loginPassphrasePanel = new LoginPassphrasePanel(hyperlinkListener);
        loginLocalFolderPanel = new LoginLocalFolderPanel(ownerFrame, hyperlinkListener);
        loginCredentialsPanel = new LoginCredentialsPanel(false, hyperlinkListener);

        // Tabbed Pane.
        tabbedPane = new JTabbedPane();
        tabbedPane.addChangeListener(this);
        tabbedPane.add(loginPassphrasePanel, "S3 Online");
        tabbedPane.add(loginLocalFolderPanel, "Local Folder");
        tabbedPane.add(loginCredentialsPanel, "Direct Login");

        int row = 0;
        this.getContentPane().setLayout(new GridBagLayout());
        this.getContentPane().add(tabbedPane, new GridBagConstraints(0, row++, 2, 1, 1, 1,
                GridBagConstraints.CENTER, GridBagConstraints.BOTH, insetsZero, 0, 0));
        this.getContentPane().add(buttonsPanel, new GridBagConstraints(0, row++, 2, 1, 1, 0,
                GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, insetsDefault, 0, 0));

        this.pack();
        this.setSize(500, 400);
        this.setLocationRelativeTo(this.getOwner());
    }

    /**
     * Event handler for this dialog.
     */
    public void actionPerformed(ActionEvent e) {
        if (e.getSource().equals(okButton)) {
            if (loginMode == LOGIN_MODE_PASSPHRASE) {
                retrieveCredentialsFromS3(loginPassphrasePanel.getPassphrase(), loginPassphrasePanel.getPassword());
            } else if (loginMode == LOGIN_MODE_LOCAL_FOLDER) {
                retrieveCredentialsFromDirectory(loginLocalFolderPanel.getHomeFolder(),
                        loginLocalFolderPanel.getAWSCredentialsFile(), loginLocalFolderPanel.getPassword());
            } else if (loginMode == LOGIN_MODE_DIRECT) {
                String[] inputErrors = loginCredentialsPanel.checkForInputErrors();
                if (inputErrors.length > 0) {
                    String errorMessages = "<html>Please correct the following errors:<ul>";
                    for (int i = 0; i < inputErrors.length; i++) {
                        errorMessages += "<li>" + inputErrors[i] + "</li>";
                    }
                    errorMessages += "</ul></html>";

                    ErrorDialog.showDialog(this, null, errorMessages, null);
                } else {
                    if (loginCredentialsPanel.getUsingDevPay()) {
                        this.awsCredentials = new AWSDevPayCredentials(loginCredentialsPanel.getAWSAccessKey(),
                                loginCredentialsPanel.getAWSSecretKey(), loginCredentialsPanel.getAWSUserToken(),
                                loginCredentialsPanel.getAWSProductToken(),
                                loginCredentialsPanel.getFriendlyName());
                    } else {
                        this.awsCredentials = new AWSCredentials(loginCredentialsPanel.getAWSAccessKey(),
                                loginCredentialsPanel.getAWSSecretKey(), loginCredentialsPanel.getFriendlyName());
                    }
                    this.setVisible(false);
                }
            }
        } else if (e.getSource().equals(storeCredentialsButton)) {
            if (loginMode == LOGIN_MODE_PASSPHRASE) {
                storeCredentialsInS3(loginPassphrasePanel.getPassphrase(), loginPassphrasePanel.getPassword());
            } else if (loginMode == LOGIN_MODE_LOCAL_FOLDER) {
                storeCredentialsInDirectory(loginLocalFolderPanel.getHomeFolder(),
                        loginLocalFolderPanel.getPassword());
            } else if (loginMode == LOGIN_MODE_DIRECT) {
                throw new IllegalStateException("Cannot store AWS credentials from Direct Login panel");
            }
        } else if (e.getSource().equals(cancelButton)) {
            this.awsCredentials = null;
            this.setVisible(false);
        }
    }

    public void stateChanged(ChangeEvent e) {
        if (e.getSource().equals(tabbedPane)) {
            loginMode = tabbedPane.getSelectedIndex();
            changedLoginMode();
        }
    }

    private void changedLoginMode() {
        if (loginMode == LOGIN_MODE_PASSPHRASE) {
            storeCredentialsButton.setEnabled(true);
        } else if (loginMode == LOGIN_MODE_LOCAL_FOLDER) {
            storeCredentialsButton.setEnabled(true);
        } else if (loginMode == LOGIN_MODE_DIRECT) {
            storeCredentialsButton.setEnabled(false);
        } else {
            throw new IllegalStateException("Invalid value for loginMode: " + loginMode);
        }
    }

    private String generateBucketNameFromPassphrase(String passphrase) throws Exception {
        return "jets3t-"
                + ServiceUtils.toHex(ServiceUtils.computeMD5Hash(passphrase.getBytes(Constants.DEFAULT_ENCODING)));
    }

    private String generateObjectKeyFromPassphrase(String passphrase, String password) throws Exception {
        String combinedString = passphrase + password;
        return ServiceUtils.toHex(ServiceUtils.computeMD5Hash(combinedString.getBytes(Constants.DEFAULT_ENCODING)))
                + "/jets3t.credentials";
    }

    private boolean validPassphraseInputs(String passphrase, String password) {
        String invalidInputsMessage = "";
        if (passphrase.length() < 6) {
            invalidInputsMessage += "Passphrase must be at least 6 characters.";
        }
        if (password.length() < 6) {
            invalidInputsMessage += (invalidInputsMessage.length() > 0 ? " and password" : "Password")
                    + " must be at least 6 characters";
        }
        if (invalidInputsMessage.length() > 0) {
            ErrorDialog.showDialog(this, hyperlinkListener, invalidInputsMessage, null);
            return false;
        } else {
            return true;
        }
    }

    private boolean validFolderInputs(boolean isStoreAction, File directory, File credentialsFile, String password,
            boolean allowLegacyPassword) {
        if (password.length() < 6) {
            if (allowLegacyPassword) {
                // Legacy password allowed for login, an error will be displayed later if it's incorrect.
            } else if (EMPTY_PASSWORD_SURROGATE.equals(password)) {
                // Surrogate empty password was used, not an error.
            } else {
                ErrorDialog.showDialog(this, hyperlinkListener,
                        "Password must be at least 6 characters. "
                                + "If you do not wish to set a password, use the password "
                                + EMPTY_PASSWORD_SURROGATE + ".",
                        null);
                return false;
            }
        }
        if (!directory.exists() || !directory.canWrite()) {
            String invalidInputsMessage = "Directory '" + directory.getAbsolutePath()
                    + "' does not exist or cannot be written to.";
            ErrorDialog.showDialog(this, hyperlinkListener, invalidInputsMessage, null);
            return false;
        }
        if (credentialsFile == null && !isStoreAction) {
            String invalidInputsMessage = "You must choose which stored login to use";
            ErrorDialog.showDialog(this, hyperlinkListener, invalidInputsMessage, null);
            return false;
        }
        return true;
    }

    private void retrieveCredentialsFromS3(String passphrase, final String password) {
        if (!validPassphraseInputs(passphrase, password)) {
            return;
        }

        final String[] bucketName = new String[1];
        final String[] credentialObjectKey = new String[1];

        try {
            bucketName[0] = generateBucketNameFromPassphrase(passphrase);
            credentialObjectKey[0] = generateObjectKeyFromPassphrase(passphrase, password);
        } catch (Exception e) {
            String message = "Unable to generate bucket name or object key";
            log.error(message, e);
            ErrorDialog.showDialog(this, hyperlinkListener, message, e);
            return;
        }

        final ProgressDialog progressDialog = new ProgressDialog(ownerFrame, "Retrieving AWS Credentials", null);
        final StartupDialog myself = this;

        (new Thread(new Runnable() {
            public void run() {
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        progressDialog.startDialog("Downloading your AWS Credentials", "", 0, 0, null, null);
                    }
                });

                S3Object encryptedCredentialsObject = null;

                try {
                    S3Service s3Service = new RestS3Service(null);
                    encryptedCredentialsObject = s3Service.getObject(new S3Bucket(bucketName[0]),
                            credentialObjectKey[0]);
                } catch (S3ServiceException e) {
                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            progressDialog.stopDialog();
                        }
                    });

                    final String errorMessage = "<html><center>Unable to find your AWS Credentials in S3"
                            + "<br><br>Please check your passphrase and password</center></html>";
                    log.error(errorMessage, e);
                    try {
                        SwingUtilities.invokeAndWait(new Runnable() {
                            public void run() {
                                ErrorDialog.showDialog(myself, hyperlinkListener, errorMessage, null);
                            }
                        });
                    } catch (InterruptedException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    } catch (InvocationTargetException e1) {
                        // TODO Auto-generated catch block
                        e1.printStackTrace();
                    }
                    return;
                }

                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        progressDialog.updateDialog("Decrypting your AWS Credentials", null, 0);
                    }
                });

                try {
                    myself.awsCredentials = AWSCredentials.load(password,
                            new BufferedInputStream(encryptedCredentialsObject.getDataInputStream()));

                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            progressDialog.stopDialog();
                        }
                    });
                    myself.setVisible(false);
                } catch (S3ServiceException e) {
                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            progressDialog.stopDialog();
                        }
                    });

                    String errorMessage = "<html><center>Unable to load your AWS Credentials from S3: "
                            + "<br><br>Please check your password</center></html>";
                    log.error(errorMessage, e);
                    ErrorDialog.showDialog(myself, hyperlinkListener, errorMessage, null);
                }

            }
        })).start();
    }

    private void storeCredentialsInS3(String passphrase, String password) {
        if (!validPassphraseInputs(passphrase, password)) {
            return;
        }

        final AWSCredentials awsCredentials = AWSCredentialsDialog.showDialog(ownerFrame,
                (loginMode == LOGIN_MODE_LOCAL_FOLDER), hyperlinkListener);
        if (awsCredentials == null) {
            return;
        }

        final String[] bucketName = new String[1];
        final String[] credentialObjectKey = new String[1];

        try {
            bucketName[0] = generateBucketNameFromPassphrase(passphrase);
            credentialObjectKey[0] = generateObjectKeyFromPassphrase(passphrase, password);
        } catch (Exception e) {
            String message = "Unable to generate bucket name or object key";
            log.error(message, e);
            ErrorDialog.showDialog(this, hyperlinkListener, message, e);
            return;
        }

        final ByteArrayInputStream[] bais = new ByteArrayInputStream[1];
        try {
            // Convert AWS Credentials into a readable input stream.
            String algorithm = myProperties.getStringProperty("crypto.algorithm", "PBEWithMD5AndDES");
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            awsCredentials.save(password, baos, algorithm);
            bais[0] = new ByteArrayInputStream(baos.toByteArray());
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            String message = "Unable to encrypt your AWS Credentials";
            log.error(message, e);
            ErrorDialog.showDialog(this, hyperlinkListener, message, e);
            return;
        }

        final ProgressDialog progressDialog = new ProgressDialog(ownerFrame, "Storing AWS Credentials", null);
        final StartupDialog myself = this;

        (new Thread(new Runnable() {
            public void run() {
                SwingUtilities.invokeLater(new Runnable() {
                    public void run() {
                        progressDialog.startDialog("Uploading your AWS Credentials", null, 0, 0, null, null);
                    }
                });

                try {
                    S3Bucket bucket = new S3Bucket(bucketName[0]);
                    S3Object encryptedCredentialsObject = new S3Object(credentialObjectKey[0]);
                    encryptedCredentialsObject.setDataInputStream(bais[0]);
                    encryptedCredentialsObject.setAcl(AccessControlList.REST_CANNED_PUBLIC_READ);

                    // Store credentials
                    S3Service s3Service = new RestS3Service(awsCredentials);
                    s3Service.createBucket(bucketName[0]);
                    s3Service.putObject(bucket, encryptedCredentialsObject);

                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            progressDialog.stopDialog();
                        }
                    });

                    JOptionPane.showMessageDialog(ownerFrame,
                            "Your AWS Credentials have been stored in your " + "S3 account\n\nBucket name: "
                                    + bucketName[0] + "\nObject key: " + credentialObjectKey[0]);
                } catch (S3ServiceException e) {
                    SwingUtilities.invokeLater(new Runnable() {
                        public void run() {
                            progressDialog.stopDialog();
                        }
                    });

                    String message = "Unable to store your AWS Credentials in S3";
                    log.error(message, e);
                    ErrorDialog.showDialog(myself, hyperlinkListener, message, e);
                }
            }
        })).start();
    }

    private void retrieveCredentialsFromDirectory(File directory, File credentialsFile, String password) {
        if (!validFolderInputs(false, directory, credentialsFile, password, true)) {
            return;
        }

        try {
            this.awsCredentials = AWSCredentials.load(password, credentialsFile);
            this.setVisible(false);
        } catch (Exception e) {
            String message = "<html><center>Unable to load your AWS Credentials from the file: " + credentialsFile
                    + "<br><br>Please check your password</center></html>";
            log.error(message, e);
            ErrorDialog.showDialog(this, hyperlinkListener, message, null);
        }
    }

    private void storeCredentialsInDirectory(File directory, String password) {
        if (!validFolderInputs(true, directory, null, password, false)) {
            return;
        }
        if (EMPTY_PASSWORD_SURROGATE.equals(password.trim())) {
            password = "";
        }

        AWSCredentials awsCredentials = AWSCredentialsDialog.showDialog(ownerFrame, true, hyperlinkListener);
        if (awsCredentials == null) {
            return;
        }
        if (awsCredentials.getFriendlyName() == null || awsCredentials.getFriendlyName().length() == 0) {
            String message = "You must enter a nickname when storing your credentials";
            log.error(message);
            ErrorDialog.showDialog(this, hyperlinkListener, message, null);
            return;
        }

        File credentialsFile = new File(directory, awsCredentials.getFriendlyName() + ".enc");

        try {
            String algorithm = myProperties.getStringProperty("crypto.algorithm", "PBEWithMD5AndDES");
            awsCredentials.save(password, credentialsFile, algorithm);
            loginLocalFolderPanel.clearPassword();
            loginLocalFolderPanel.refreshStoredCredentialsTable();

            JOptionPane.showMessageDialog(ownerFrame,
                    "Your AWS Credentials have been stored in the file:\n" + credentialsFile.getAbsolutePath());
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            String message = "Unable to encrypt your AWS Credentials to a folder";
            log.error(message, e);
            ErrorDialog.showDialog(this, hyperlinkListener, message, e);
        }
    }

    public AWSCredentials getAWSCredentials() {
        return this.awsCredentials;
    }

    /**
     * Creates stand-alone dialog box for testing only.
     *
     * @param args
     * @throws Exception
     */
    public static void main(String args[]) throws Exception {
        //        String algorithm = Jets3tProperties.getInstance(Constants.JETS3T_PROPERTIES_FILENAME)
        //            .getStringProperty("crypto.algorithm", "PBEWithMD5AndDES");
        //        File file = new File("/Users/jmurty/Desktop/test.enc");
        //        AWSCredentials awsCredentialsTest = new AWSCredentials("a", "b");
        //        awsCredentialsTest.save("please", file, algorithm);
        //        System.err.println("Saved: " + awsCredentialsTest);
        //        System.err.println("Loaded: " + AWSCredentials.load("please", file));
        //        if (true)
        //            return;
        //
        JFrame f = new JFrame();

        HyperlinkActivatedListener listener = new HyperlinkActivatedListener() {
            private static final long serialVersionUID = -225585129296632961L;

            public void followHyperlink(URL url, String target) {
                BareBonesBrowserLaunch.openURL(url.toString());
            }
        };

        StartupDialog startupDialog = new StartupDialog(f,
                Jets3tProperties.getInstance(Constants.JETS3T_PROPERTIES_FILENAME), listener);
        startupDialog.setVisible(true);
        AWSCredentials awsCredentials = startupDialog.getAWSCredentials();
        startupDialog.dispose();

        if (awsCredentials != null) {
            System.out.println("AWS Credentials: " + awsCredentials.getLogString());
        } else {
            System.out.println("AWS Credentials: null");
        }

        f.dispose();
    }

}