org.apache.hadoop.eclipse.actions.DFSActionImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.hadoop.eclipse.actions.DFSActionImpl.java

Source

/**
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.hadoop.eclipse.actions;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.hadoop.eclipse.ImageLibrary;
import org.apache.hadoop.eclipse.dfs.DFSActions;
import org.apache.hadoop.eclipse.dfs.DFSFile;
import org.apache.hadoop.eclipse.dfs.DFSFolder;
import org.apache.hadoop.eclipse.dfs.DFSLocation;
import org.apache.hadoop.eclipse.dfs.DFSLocationsRoot;
import org.apache.hadoop.eclipse.dfs.DFSPath;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.PlatformObject;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IPersistableElement;
import org.eclipse.ui.IStorageEditorInput;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;

/**
 * Actual implementation of DFS actions
 */
public class DFSActionImpl implements IObjectActionDelegate {

    private ISelection selection;

    private IWorkbenchPart targetPart;

    /* @inheritDoc */
    public void setActivePart(IAction action, IWorkbenchPart targetPart) {
        this.targetPart = targetPart;
    }

    /* @inheritDoc */
    public void run(IAction action) {

        // Ignore non structured selections
        if (!(this.selection instanceof IStructuredSelection))
            return;

        // operate on the DFS asynchronously to prevent blocking the main UI
        final IStructuredSelection ss = (IStructuredSelection) selection;
        final String actionId = action.getActionDefinitionId();
        Display.getDefault().asyncExec(new Runnable() {
            public void run() {
                try {
                    switch (DFSActions.getById(actionId)) {
                    case DELETE: {
                        delete(ss);
                        break;
                    }
                    case OPEN: {
                        open(ss);
                        break;
                    }
                    case MKDIR: {
                        mkdir(ss);
                        break;
                    }
                    case UPLOAD_FILES: {
                        uploadFilesToDFS(ss);
                        break;
                    }
                    case UPLOAD_DIR: {
                        uploadDirectoryToDFS(ss);
                        break;
                    }
                    case REFRESH: {
                        refresh(ss);
                        break;
                    }
                    case DOWNLOAD: {
                        downloadFromDFS(ss);
                        break;
                    }
                    case RECONNECT: {
                        reconnect(ss);
                        break;
                    }
                    case DISCONNECT: {
                        disconnect(ss);
                        break;
                    }
                    default: {
                        System.err.printf("Unhandled DFS Action: " + actionId);
                        break;
                    }
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                    MessageDialog.openError(Display.getDefault().getActiveShell(), "DFS Action error",
                            "An error occurred while performing DFS operation: " + e.getMessage());
                }
            }
        });
    }

    /**
     * Create a new sub-folder into an existing directory
     * 
     * @param selection
     */
    private void mkdir(IStructuredSelection selection) {
        List<DFSFolder> folders = filterSelection(DFSFolder.class, selection);
        if (folders.size() >= 1) {
            DFSFolder folder = folders.get(0);
            InputDialog dialog = new InputDialog(Display.getCurrent().getActiveShell(), "Create subfolder",
                    "Enter the name of the subfolder", "", null);
            if (dialog.open() == InputDialog.OK)
                folder.mkdir(dialog.getValue());
        }
    }

    /**
     * Implement the import action (upload files from the current machine to
     * HDFS)
     * 
     * @param object
     * @throws SftpException
     * @throws JSchException
     * @throws InvocationTargetException
     * @throws InterruptedException
     */
    private void uploadFilesToDFS(IStructuredSelection selection)
            throws InvocationTargetException, InterruptedException {

        // Ask the user which files to upload
        FileDialog dialog = new FileDialog(Display.getCurrent().getActiveShell(), SWT.OPEN | SWT.MULTI);
        dialog.setText("Select the local files to upload");
        dialog.open();

        List<File> files = new ArrayList<File>();
        for (String fname : dialog.getFileNames())
            files.add(new File(dialog.getFilterPath() + File.separator + fname));

        // TODO enable upload command only when selection is exactly one folder
        List<DFSFolder> folders = filterSelection(DFSFolder.class, selection);
        if (folders.size() >= 1)
            uploadToDFS(folders.get(0), files);
    }

    /**
     * Implement the import action (upload directory from the current machine
     * to HDFS)
     * 
     * @param object
     * @throws SftpException
     * @throws JSchException
     * @throws InvocationTargetException
     * @throws InterruptedException
     */
    private void uploadDirectoryToDFS(IStructuredSelection selection)
            throws InvocationTargetException, InterruptedException {

        // Ask the user which local directory to upload
        DirectoryDialog dialog = new DirectoryDialog(Display.getCurrent().getActiveShell(), SWT.OPEN | SWT.MULTI);
        dialog.setText("Select the local file or directory to upload");

        String dirName = dialog.open();
        final File dir = new File(dirName);
        List<File> files = new ArrayList<File>();
        files.add(dir);

        // TODO enable upload command only when selection is exactly one folder
        final List<DFSFolder> folders = filterSelection(DFSFolder.class, selection);
        if (folders.size() >= 1)
            uploadToDFS(folders.get(0), files);

    }

    private void uploadToDFS(final DFSFolder folder, final List<File> files)
            throws InvocationTargetException, InterruptedException {

        PlatformUI.getWorkbench().getProgressService().busyCursorWhile(new IRunnableWithProgress() {
            public void run(IProgressMonitor monitor) throws InvocationTargetException {

                int work = 0;
                for (File file : files)
                    work += computeUploadWork(file);

                monitor.beginTask("Uploading files to distributed file system", work);

                for (File file : files) {
                    try {
                        folder.upload(monitor, file);

                    } catch (IOException ioe) {
                        ioe.printStackTrace();
                        MessageDialog.openError(null, "Upload files to distributed file system",
                                "Upload failed.\n" + ioe);
                    }
                }

                monitor.done();

                // Update the UI
                folder.doRefresh();
            }
        });
    }

    private void reconnect(IStructuredSelection selection) {
        for (DFSLocation location : filterSelection(DFSLocation.class, selection))
            location.reconnect();
    }

    private void disconnect(IStructuredSelection selection) {
        if (selection.size() != 1)
            return;

        Object first = selection.getFirstElement();
        if (!(first instanceof DFSLocationsRoot))
            return;

        DFSLocationsRoot root = (DFSLocationsRoot) first;
        root.disconnect();
        root.refresh();
    }

    /**
     * Implements the Download action from HDFS to the current machine
     * 
     * @param object
     * @throws SftpException
     * @throws JSchException
     * @throws InterruptedException
     * @throws InvocationTargetException
     */
    private void downloadFromDFS(IStructuredSelection selection)
            throws InvocationTargetException, InterruptedException {

        // Ask the user where to put the downloaded files
        DirectoryDialog dialog = new DirectoryDialog(Display.getCurrent().getActiveShell());
        dialog.setText("Copy to local directory");
        dialog.setMessage("Copy the selected files and directories from the "
                + "distributed filesystem to a local directory");
        String directory = dialog.open();

        if (directory == null)
            return;

        final File dir = new File(directory);
        if (!dir.exists())
            dir.mkdirs();

        if (!dir.isDirectory()) {
            MessageDialog.openError(null, "Download to local file system",
                    "Invalid directory location: \"" + dir + "\"");
            return;
        }

        final List<DFSPath> paths = filterSelection(DFSPath.class, selection);

        PlatformUI.getWorkbench().getProgressService().busyCursorWhile(new IRunnableWithProgress() {
            public void run(IProgressMonitor monitor) throws InvocationTargetException {

                int work = 0;
                for (DFSPath path : paths)
                    work += path.computeDownloadWork();

                monitor.beginTask("Downloading files to local file system", work);

                for (DFSPath path : paths) {
                    if (monitor.isCanceled())
                        return;
                    try {
                        path.downloadToLocalDirectory(monitor, dir);
                    } catch (Exception e) {
                        // nothing we want to do here
                        e.printStackTrace();
                    }
                }

                monitor.done();
            }
        });
    }

    /**
     * Open the selected DfsPath in the editor window
     * 
     * @param selection
     * @throws JSchException
     * @throws IOException
     * @throws PartInitException
     * @throws InvocationTargetException
     * @throws InterruptedException
     */
    private void open(IStructuredSelection selection)
            throws IOException, PartInitException, InvocationTargetException, InterruptedException {

        for (DFSFile file : filterSelection(DFSFile.class, selection)) {

            IStorageEditorInput editorInput = new DFSFileEditorInput(file);
            targetPart.getSite().getWorkbenchWindow().getActivePage().openEditor(editorInput,
                    "org.eclipse.ui.DefaultTextEditor");
        }
    }

    /**
     * @param selection
     * @throws JSchException
     */
    private void refresh(IStructuredSelection selection) {
        for (DFSPath path : filterSelection(DFSPath.class, selection))
            path.refresh();

    }

    private void delete(IStructuredSelection selection) {
        List<DFSPath> list = filterSelection(DFSPath.class, selection);
        if (list.isEmpty())
            return;

        StringBuffer msg = new StringBuffer();
        msg.append("Are you sure you want to delete " + "the following files from the distributed file system?\n");
        for (DFSPath path : list)
            msg.append(path.getPath()).append("\n");

        if (MessageDialog.openConfirm(null, "Confirm Delete from DFS", msg.toString())) {

            Set<DFSPath> toRefresh = new HashSet<DFSPath>();
            for (DFSPath path : list) {
                path.delete();
                toRefresh.add(path.getParent());
            }

            for (DFSPath path : toRefresh) {
                path.refresh();
            }
        }
    }

    /* @inheritDoc */
    public void selectionChanged(IAction action, ISelection selection) {
        this.selection = selection;
    }

    /**
     * Extract the list of <T> from the structured selection
     * 
     * @param clazz the class T
     * @param selection the structured selection
     * @return the list of <T> it contains
     */
    private static <T> List<T> filterSelection(Class<T> clazz, IStructuredSelection selection) {
        List<T> list = new ArrayList<T>();
        for (Object obj : selection.toList()) {
            if (clazz.isAssignableFrom(obj.getClass())) {
                list.add((T) obj);
            }
        }
        return list;
    }

    private static int computeUploadWork(File file) {
        if (file.isDirectory()) {
            int contentWork = 1;
            for (File child : file.listFiles())
                contentWork += computeUploadWork(child);
            return contentWork;

        } else if (file.isFile()) {
            return 1 + (int) (file.length() / 1024);

        } else {
            return 0;
        }
    }

}

/**
 * Adapter to allow the viewing of a DfsFile in the Editor window
 */
class DFSFileEditorInput extends PlatformObject implements IStorageEditorInput {

    private DFSFile file;

    /**
     * Constructor
     * 
     * @param file
     */
    DFSFileEditorInput(DFSFile file) {
        this.file = file;
    }

    /* @inheritDoc */
    public String getToolTipText() {
        return file.toDetailedString();
    }

    /* @inheritDoc */
    public IPersistableElement getPersistable() {
        return null;
    }

    /* @inheritDoc */
    public String getName() {
        return file.toString();
    }

    /* @inheritDoc */
    public ImageDescriptor getImageDescriptor() {
        return ImageLibrary.get("dfs.file.editor");
    }

    /* @inheritDoc */
    public boolean exists() {
        return true;
    }

    /* @inheritDoc */
    public IStorage getStorage() throws CoreException {
        return file.getIStorage();
    }
};