org.pentaho.amazon.s3.S3VfsFileChooserDialog.java Source code

Java tutorial

Introduction

Here is the source code for org.pentaho.amazon.s3.S3VfsFileChooserDialog.java

Source

/*******************************************************************************
 *
 * Pentaho Big Data
 *
 * Copyright (C) 2002-2013 by Pentaho : http://www.pentaho.com
 *
 *******************************************************************************
 *
 * 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.pentaho.amazon.s3;

import com.amazonaws.auth.AWSCredentials;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.AmazonS3Exception;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemException;
import org.apache.commons.vfs.FileSystemOptions;
import org.apache.commons.vfs.auth.StaticUserAuthenticator;
import org.apache.commons.vfs.impl.DefaultFileSystemConfigBuilder;
import org.apache.commons.vfs.provider.GenericFileName;
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.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.MessageBox;
import org.pentaho.amazon.AmazonS3FileSystemBootstrap;
import org.pentaho.amazon.AmazonSpoonPlugin;
import org.pentaho.di.core.Const;
import org.pentaho.di.core.Props;
import org.pentaho.di.core.encryption.Encr;
import org.pentaho.di.core.exception.KettleFileException;
import org.pentaho.di.core.logging.LogChannel;
import org.pentaho.di.core.variables.VariableSpace;
import org.pentaho.di.core.variables.Variables;
import org.pentaho.di.core.vfs.KettleVFS;
import org.pentaho.di.i18n.BaseMessages;
import org.pentaho.di.ui.core.widget.TextVar;
import org.pentaho.di.ui.spoon.Spoon;
import org.pentaho.s3.vfs.S3FileObject;
import org.pentaho.s3.vfs.S3FileProvider;
import org.pentaho.vfs.ui.CustomVfsUiPanel;
import org.pentaho.vfs.ui.VfsFileChooserDialog;

public class S3VfsFileChooserDialog extends CustomVfsUiPanel {

    // for message resolution
    private static Class<?> PKG = AmazonSpoonPlugin.class;

    // for logging
    private LogChannel log = new LogChannel(this);

    // URL label and field
    private Label wlAccessKey;
    private TextVar wAccessKey;
    private GridData fdlAccessKey, fdAccessKey;

    // Port label and field
    // private Label wlBucket;
    // private Text wBucket;
    // private GridData fdlBucket, fdBucket;

    // UserID label and field
    private Label wlSecretKey;
    private TextVar wSecretKey;
    private GridData fdlSecretKey, fdSecretKey;

    // Place holder - for creating a blank widget in a grid layout
    private Label wPlaceHolderLabel;
    private GridData fdlPlaceHolderLabel;

    // Connection button
    private Button wConnectionButton;
    private GridData fdConnectionButton;

    // Default root file - used to avoid NPE when rootFile was not provided
    // and the browser is resolved
    FileObject defaultInitialFile = null;

    // File objects to keep track of when the user selects the radio buttons
    FileObject localRootFile = null;
    String localOpenFromFolder = null;
    FileObject s3RootFile = null;
    String s3OpenFromFolder = null;

    FileObject rootFile = null;
    FileObject initialFile = null;
    VfsFileChooserDialog vfsFileChooserDialog = null;

    private String accessKey;
    private String secretKey;

    private StaticUserAuthenticator userAuthenticator = null;

    public S3VfsFileChooserDialog(VfsFileChooserDialog vfsFileChooserDialog, FileObject rootFile,
            FileObject initialFile) {
        super(S3FileProvider.SCHEME, AmazonS3FileSystemBootstrap.getS3FileSystemDisplayText(), vfsFileChooserDialog,
                SWT.NONE);

        this.vfsFileChooserDialog = vfsFileChooserDialog;
        this.rootFile = rootFile;
        this.initialFile = initialFile;

        setLayout(new GridLayout());

        // Create the s3 panel
        createConnectionPanel();
        initializeConnectionPanel();
    }

    private void createConnectionPanel() {

        // The Connection group
        Group connectionGroup = new Group(this, SWT.SHADOW_ETCHED_IN);
        connectionGroup.setText(BaseMessages.getString(PKG, "S3VfsFileChooserDialog.ConnectionGroup.Label")); //$NON-NLS-1$;
        GridLayout connectionGroupLayout = new GridLayout();
        connectionGroupLayout.marginWidth = 5;
        connectionGroupLayout.marginHeight = 5;
        connectionGroupLayout.verticalSpacing = 5;
        connectionGroupLayout.horizontalSpacing = 5;
        GridData gData = new GridData(SWT.FILL, SWT.FILL, true, false);
        connectionGroup.setLayoutData(gData);
        connectionGroup.setLayout(connectionGroupLayout);

        // The composite we need in the group
        Composite textFieldPanel = new Composite(connectionGroup, SWT.NONE);
        GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
        textFieldPanel.setLayoutData(gridData);
        textFieldPanel.setLayout(new GridLayout(3, false));

        // URL label and text field
        wlAccessKey = new Label(textFieldPanel, SWT.RIGHT);
        wlAccessKey.setText(BaseMessages.getString(PKG, "S3VfsFileChooserDialog.AccessKey.Label")); //$NON-NLS-1$
        fdlAccessKey = new GridData();
        fdlAccessKey.widthHint = 75;
        wlAccessKey.setLayoutData(fdlAccessKey);
        wAccessKey = new TextVar(getVariableSpace(), textFieldPanel,
                SWT.PASSWORD | SWT.SINGLE | SWT.LEFT | SWT.BORDER);
        fdAccessKey = new GridData();
        fdAccessKey.widthHint = 150;
        wAccessKey.setLayoutData(fdAccessKey);
        wAccessKey.setText(Encr.decryptPasswordOptionallyEncrypted(
                Props.getInstance().getCustomParameter("S3VfsFileChooserDialog.AccessKey", "")));

        wAccessKey.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent arg0) {
                handleConnectionButton();
            }
        });

        // // Place holder
        wPlaceHolderLabel = new Label(textFieldPanel, SWT.RIGHT);
        wPlaceHolderLabel.setText("");
        fdlPlaceHolderLabel = new GridData();
        fdlPlaceHolderLabel.widthHint = 75;
        wPlaceHolderLabel.setLayoutData(fdlPlaceHolderLabel);

        // UserID label and field
        wlSecretKey = new Label(textFieldPanel, SWT.RIGHT);
        wlSecretKey.setText(BaseMessages.getString(PKG, "S3VfsFileChooserDialog.SecretKey.Label"));
        fdlSecretKey = new GridData();
        fdlSecretKey.widthHint = 75;
        wlSecretKey.setLayoutData(fdlSecretKey);

        wSecretKey = new TextVar(getVariableSpace(), textFieldPanel,
                SWT.PASSWORD | SWT.SINGLE | SWT.LEFT | SWT.BORDER);
        fdSecretKey = new GridData();
        fdSecretKey.widthHint = 300;
        wSecretKey.setLayoutData(fdSecretKey);
        wSecretKey.setText(Encr.decryptPasswordOptionallyEncrypted(
                Props.getInstance().getCustomParameter("S3VfsFileChooserDialog.SecretKey", "")));

        wSecretKey.addModifyListener(new ModifyListener() {
            public void modifyText(ModifyEvent arg0) {
                handleConnectionButton();
            }
        });

        // bucket
        // wlBucket = new Label(textFieldPanel, SWT.RIGHT);
        //    wlBucket.setText(BaseMessages.getString(PKG, "S3VfsFileChooserDialog.Bucket.Label")); //$NON-NLS-1$
        // fdlBucket = new GridData();
        // fdlBucket.widthHint = 75;
        // wlBucket.setLayoutData(fdlBucket);
        //
        // wBucket = new Text(textFieldPanel, SWT.SINGLE | SWT.LEFT | SWT.BORDER);
        // fdBucket = new GridData();
        // fdBucket.widthHint = 150;
        // wBucket.setLayoutData(fdBucket);
        // wBucket.addKeyListener(new KeyAdapter() {
        // public void keyPressed(KeyEvent e) {
        // handleConnectionButton();
        // }
        // });

        // Connection button
        wConnectionButton = new Button(textFieldPanel, SWT.CENTER);
        fdConnectionButton = new GridData();
        fdConnectionButton.widthHint = 75;
        wConnectionButton.setLayoutData(fdConnectionButton);

        wConnectionButton.setText(BaseMessages.getString(PKG, "S3VfsFileChooserDialog.ConnectionButton.Label"));
        wConnectionButton.addSelectionListener(new SelectionAdapter() {
            public void widgetSelected(SelectionEvent e) {

                try {
                    // let's verify the accessKey/secretKey
                    AmazonS3 s3Client = new AmazonS3Client(new AWSCredentials() {

                        public String getAWSSecretKey() {
                            return Encr.decryptPasswordOptionallyEncrypted(
                                    environmentSubstitute(wSecretKey.getText()));
                        }

                        public String getAWSAccessKeyId() {
                            return Encr.decryptPasswordOptionallyEncrypted(
                                    environmentSubstitute(wAccessKey.getText()));
                        }
                    });
                    s3Client.getS3AccountOwner();

                    // s3 credentials valid, continue
                    Props.getInstance().setCustomParameter("S3VfsFileChooserDialog.AccessKey",
                            Encr.encryptPasswordIfNotUsingVariables(wAccessKey.getText()));
                    Props.getInstance().setCustomParameter("S3VfsFileChooserDialog.SecretKey",
                            Encr.encryptPasswordIfNotUsingVariables(wSecretKey.getText()));

                    try {
                        FileObject root = rootFile;
                        root = resolveFile(buildS3FileSystemUrlString());
                        vfsFileChooserDialog.setSelectedFile(root);
                        vfsFileChooserDialog.setRootFile(root);
                        rootFile = root;
                    } catch (FileSystemException e1) {
                        MessageBox box = new MessageBox(getShell());
                        box.setText(BaseMessages.getString(PKG, "S3VfsFileChooserDialog.error")); //$NON-NLS-1$
                        box.setMessage(e1.getMessage());
                        log.logError(e1.getMessage(), e1);
                        box.open();
                        return;
                    }

                } catch (AmazonS3Exception ex) {
                    // if anything went wrong, we have to show an error dialog
                    MessageBox box = new MessageBox(getShell());
                    box.setText(BaseMessages.getString(PKG, "S3VfsFileChooserDialog.error")); //$NON-NLS-1$
                    box.setMessage(ex.getMessage());
                    log.logError(ex.getMessage(), ex);
                    box.open();
                    return;
                }
            }
        });

        // set the tab order
        textFieldPanel.setTabList(new Control[] { wAccessKey, wSecretKey, wConnectionButton });
        // textFieldPanel.setTabList(new Control[] { wAccessKey, wBucket, wSecretKey, wPassword, wConnectionButton });
    }

    private VariableSpace getVariableSpace() {
        if (Spoon.getInstance().getActiveTransformation() != null) {
            return Spoon.getInstance().getActiveTransformation();
        } else if (Spoon.getInstance().getActiveJob() != null) {
            return Spoon.getInstance().getActiveJob();
        } else {
            return new Variables();
        }
    }

    private String environmentSubstitute(String str) {
        return getVariableSpace().environmentSubstitute(str);
    }

    /**
     * Build a URL given Url and Port provided by the user.
     *
     * @return
     * @TODO: relocate to a s3 helper class or similar
     */
    public String buildS3FileSystemUrlString() {
        return S3FileProvider.SCHEME + "://s3/";
    }

    @Override
    public void activate() {
        wAccessKey.setVariables(getVariableSpace());
        wSecretKey.setVariables(getVariableSpace());
        vfsFileChooserDialog.setRootFile(null);
        vfsFileChooserDialog.setInitialFile(null);
        vfsFileChooserDialog.openFileCombo.setText("s3://");
        vfsFileChooserDialog.vfsBrowser.fileSystemTree.removeAll();
        super.activate();
    }

    private void initializeConnectionPanel() {

        if (initialFile != null && initialFile instanceof S3FileObject) {
            // populate the server and port fields
            try {
                GenericFileName genericFileName = (GenericFileName) initialFile.getFileSystem().getRoot().getName();
                wAccessKey.setText(genericFileName.getUserName() == null ? "" : genericFileName.getUserName());
                wSecretKey.setText(genericFileName.getPassword()); //$NON-NLS-1$
                // wBucket.setText(String.valueOf(genericFileName.getPort()));
            } catch (FileSystemException fse) {
                showMessageAndLog("S3VfsFileChooserDialog.error", "S3VfsFileChooserDialog.FileSystem.error",
                        fse.getMessage());
            }
        }

        handleConnectionButton();
    }

    private void showMessageAndLog(String title, String message, String messageToLog) {
        MessageBox box = new MessageBox(getShell());
        box.setText(BaseMessages.getString(PKG, title)); //$NON-NLS-1$
        box.setMessage(BaseMessages.getString(PKG, message));
        log.logError(messageToLog);
        box.open();
    }

    private void handleConnectionButton() {
        if (!Const.isEmpty(wAccessKey.getText()) && !Const.isEmpty(wSecretKey.getText())) {
            accessKey = Encr.decryptPasswordOptionallyEncrypted(
                    getVariableSpace().environmentSubstitute(wAccessKey.getText()));
            secretKey = Encr.decryptPasswordOptionallyEncrypted(
                    getVariableSpace().environmentSubstitute(wSecretKey.getText()));
            wConnectionButton.setEnabled(true);
        } else {
            accessKey = null;
            secretKey = null;
            wConnectionButton.setEnabled(false);
        }
    }

    public String getAccessKey() {
        return accessKey;
    }

    public String getSecretKey() {
        return secretKey;
    }

    public FileObject resolveFile(String fileUri) throws FileSystemException {
        try {
            return KettleVFS.getFileObject(fileUri, getVariableSpace(), getFileSystemOptions());
        } catch (KettleFileException e) {
            throw new FileSystemException(e);
        }
    }

    public FileObject resolveFile(String fileUri, FileSystemOptions opts) throws FileSystemException {
        try {
            return KettleVFS.getFileObject(fileUri, getVariableSpace(), opts);
        } catch (KettleFileException e) {
            throw new FileSystemException(e);
        }
    }

    protected FileSystemOptions getFileSystemOptions() throws FileSystemException {
        FileSystemOptions opts = new FileSystemOptions();

        if (!Const.isEmpty(getAccessKey()) || !Const.isEmpty(getSecretKey())) {
            // create a FileSystemOptions with user & password
            StaticUserAuthenticator userAuthenticator = new StaticUserAuthenticator(null,
                    Encr.decryptPasswordOptionallyEncrypted(
                            getVariableSpace().environmentSubstitute(getAccessKey())),
                    Encr.decryptPasswordOptionallyEncrypted(
                            getVariableSpace().environmentSubstitute(getSecretKey())));

            DefaultFileSystemConfigBuilder.getInstance().setUserAuthenticator(opts, userAuthenticator);
        }
        return opts;
    }
}